libStatGen Software  1
WriteFiles.cpp
1 /*
2  * Copyright (C) 2010 Regents of the University of Michigan
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "SamFile.h"
19 #include "WriteFiles.h"
20 #include "TestValidate.h"
21 
22 #include <assert.h>
23 #include <stdio.h>
24 
25 void testWrite()
26 {
27  testHeaderWrite();
28  testWriteCopiedHeader("testFiles/testSam.sam");
29 #ifdef __ZLIB_AVAILABLE__
30  testWriteCopiedHeader("testFiles/testBam.bam");
31 #endif
32 }
33 
34 void testHeaderWrite()
35 {
36  SamFile samOut;
37 
38  samOut.OpenForWrite("results/MyTestOut.sam");
39 
40  // Create a sam header.
41  SamFileHeader samHeader;
42 
43  std::string headerString = "";
44 
45  // Test getting HD & PG and the HD-SO tag when they do not exist.
46  assert(samHeader.getHD() == NULL);
47  assert(samHeader.getPG("1") == NULL);
48  assert(strcmp(samHeader.getTagSO(), "") == 0);
49 
50  // Test removing the HD tag that does not exist.
51  assert(samHeader.removeHD() == true);
52  assert(samHeader.getHD() == NULL);
53  assert(strcmp(samHeader.getHDTagValue("VN"), "") == 0);
54  assert(samHeader.getHeaderString(headerString) == true);
55  assert(headerString == "");
56 
57  char type[3] = "HD";
58  char tag[3] = "VN";
59  // Verify it has not yet been added to the parsed header.
60  assert(strcmp(samHeader.getHDTagValue("VN"), "") == 0);
61  assert(samHeader.addHeaderLine(type, tag, "1.0") == true);
62  assert(samHeader.getHeaderString(headerString) == true);
63  assert(headerString == "@HD\tVN:1.0\n");
64 
65  // Verify it was added to the parsed header.
66  assert(strcmp(samHeader.getHDTagValue("VN"), "1.0") == 0);
67 
68  type[0] = 'S';
69  type[1] = 'Q';
70  tag[0] = 'L';
71  tag[1] = 'N';
72  // Cannot add SQ LN tag without adding the SN tag also.
73  assert(samHeader.addHeaderLine(type, tag, "123") == false);
74  assert(samHeader.getHeaderString(headerString) == true);
75  assert(headerString == "@HD\tVN:1.0\n");
76 
77  // Has not yet been added, so returns blank.
78  assert(strcmp(samHeader.getSQTagValue("LN", "chr20"), "") == 0);
79 
80  // Can't add the SQ type without a LN.
81  std::string line = "@SQ\tSN:123";
82  assert(samHeader.addHeaderLine(line.c_str()) == false);
83  assert(samHeader.getHeaderString(headerString) == true);
84  assert(headerString == "@HD\tVN:1.0\n");
85 
86  // Successfully add a SQ line.
87  line = "@SQ\tLN:123\tSN:chr20";
88  assert(samHeader.addHeaderLine(line.c_str()) == true);
89  assert(samHeader.getHeaderString(headerString) == true);
90  assert(headerString == "@HD\tVN:1.0\n@SQ\tLN:123\tSN:chr20\n");
91  // Verify it was added to the parsed header.
92  assert(strcmp(samHeader.getSQTagValue("LN", "chr20"), "123") == 0);
93 
94  // Test to make sure nothing changes if try to copy into self.
95  samHeader = samHeader;
96  assert(samHeader.addHeaderLine(line.c_str()) == false);
97  assert(samHeader.getHeaderString(headerString) == true);
98  assert(headerString == "@HD\tVN:1.0\n@SQ\tLN:123\tSN:chr20\n");
99  // Verify it was added to the parsed header.
100  assert(strcmp(samHeader.getSQTagValue("LN", "chr20"), "123") == 0);
101 
102  samHeader.copy(samHeader);
103  assert(samHeader.addHeaderLine(line.c_str()) == false);
104  assert(samHeader.getHeaderString(headerString) == true);
105  assert(headerString == "@HD\tVN:1.0\n@SQ\tLN:123\tSN:chr20\n");
106  // Verify it was added to the parsed header.
107  assert(strcmp(samHeader.getSQTagValue("LN", "chr20"), "123") == 0);
108 
109  // Test adding an HD that is already there.
110  assert(samHeader.addHeaderLine("@HD\tVN:1.1") == false);
111  assert(samHeader.getHeaderString(headerString) == true);
112  assert(headerString == "@HD\tVN:1.0\n@SQ\tLN:123\tSN:chr20\n");
113  // Verify it was added to the parsed header.
114  assert(strcmp(samHeader.getHDTagValue("VN"), "1.0") == 0);
115 
116  // Test copying the header.
117  SamFileHeader newHeader = samHeader;
118  assert(newHeader.getHeaderString(headerString) == true);
119  assert(headerString == "@HD\tVN:1.0\n@SQ\tLN:123\tSN:chr20\n");
120  // Verify it was added to the parsed header.
121  assert(strcmp(newHeader.getSQTagValue("LN", "chr20"), "123") == 0);
122 
123 
124  // Modify one of the tags.
125  assert(samHeader.setHDTag("VN", "1.1") == true);
126  assert(samHeader.getHeaderString(headerString) == true);
127  assert(headerString == "@HD\tVN:1.1\n@SQ\tLN:123\tSN:chr20\n");
128  // Verify it was modified.
129  assert(strcmp(samHeader.getHDTagValue("VN"), "1.1") == 0);
130 
131  // Remove the version.
132  assert(samHeader.setHDTag("VN", "") == true);
133  assert(samHeader.getHeaderString(headerString) == true);
134  assert(headerString == "@SQ\tLN:123\tSN:chr20\n");
135  // Verify it was removed.
136  assert(strcmp(samHeader.getHDTagValue("VN"), "") == 0);
137 
138  // Remove the SN from the SQ type - fails because SN is the key.
139  assert(samHeader.setSQTag("SN", "", "chr20") == false);
140  assert(samHeader.getHeaderString(headerString) == true);
141  assert(headerString == "@SQ\tLN:123\tSN:chr20\n");
142  // Verify it was not removed.
143  assert(strcmp(samHeader.getSQTagValue("SN", "chr20"), "chr20") == 0);
144  assert(strcmp(samHeader.getSQTagValue("LN", "chr20"), "123") == 0);
145 
146  // Can't remove the LN from the SQ type
147  assert(samHeader.setSQTag("LN", "", "chr20") == false);
148  assert(samHeader.getHeaderString(headerString) == true);
149  assert(headerString == "@SQ\tLN:123\tSN:chr20\n");
150  // Verify it was not removed.
151  assert(strcmp(samHeader.getSQTagValue("LN", "chr20"), "123") == 0);
152  assert(strcmp(samHeader.getSQTagValue("SN", "chr20"), "chr20") == 0);
153 
154  // Delete the SQ line.
155  assert(samHeader.removeSQ("chr20") == true);
156  // There is no header string.
157  assert(samHeader.getHeaderString(headerString) == true);
158  assert(headerString == "");
159  // Verify it was removed.
160  assert(strcmp(samHeader.getSQTagValue("SN", "chr20"), "") == 0);
161  assert(strcmp(samHeader.getSQTagValue("LN", "chr20"), "") == 0);
162 
163  // Create an SQ record and add it back in.
164  SamHeaderSQ* sq = new SamHeaderSQ();
165  assert(sq->setTag("LN", "123") == true);
166  assert(sq->setTag("SN", "chr20") == true);
167  assert(samHeader.addSQ(sq) == true);
168  assert(samHeader.getHeaderString(headerString) == true);
169  assert(headerString == "@SQ\tLN:123\tSN:chr20\n");
170  // Verify it was added.
171  assert(strcmp(samHeader.getSQTagValue("SN", "chr20"), "chr20") == 0);
172  assert(strcmp(samHeader.getSQTagValue("LN", "chr20"), "123") == 0);
173 
174  // Modify a tag.
175  assert(sq->setTag("LN", "222") == true);
176  assert(samHeader.getHeaderString(headerString) == true);
177  assert(headerString == "@SQ\tLN:222\tSN:chr20\n");
178  // Verify it was modified.
179  assert(strcmp(samHeader.getSQTagValue("SN", "chr20"), "chr20") == 0);
180  assert(strcmp(samHeader.getSQTagValue("LN", "chr20"), "222") == 0);
181 
182 
183  // Test adding another SQ with the same key.
184  SamHeaderSQ* sq2 = new SamHeaderSQ();
185  assert(sq2->setTag("LN", "333") == true);
186  assert(sq2->setTag("SN", "chr20") == true);
187  assert(samHeader.addSQ(sq2) == false);
188  assert(samHeader.getHeaderString(headerString) == true);
189  assert(headerString == "@SQ\tLN:222\tSN:chr20\n");
190  // Verify it was not added.
191  assert(strcmp(samHeader.getSQTagValue("SN", "chr20"), "chr20") == 0);
192  assert(strcmp(samHeader.getSQTagValue("LN", "chr20"), "222") == 0);
193  delete sq2;
194 
195  // Add a new tag to the SQ tag.
196  assert(samHeader.setSQTag("AS", "HG18", "chr20") == true);
197  assert(samHeader.getHeaderString(headerString) == true);
198  assert(headerString == "@SQ\tLN:222\tSN:chr20\tAS:HG18\n");
199  // Verify it was added.
200  assert(strcmp(samHeader.getSQTagValue("AS", "chr20"), "HG18") == 0);
201 
202  // Modify the AS tag.
203  assert(samHeader.setSQTag("AS", "HG19", "chr20") == true);
204  assert(samHeader.getHeaderString(headerString) == true);
205  assert(headerString == "@SQ\tLN:222\tSN:chr20\tAS:HG19\n");
206  // Verify it was added.
207  assert(strcmp(samHeader.getSQTagValue("AS", "chr20"), "HG19") == 0);
208 
209  // Add a new tag .
210  sq2 = new SamHeaderSQ();
211  assert(sq2->setTag("LN", "333") == true);
212  assert(sq2->setTag("SN", "chr1") == true);
213  assert(samHeader.addSQ(sq2) == true);
214  assert(samHeader.getHeaderString(headerString) == true);
215  assert(headerString ==
216  "@SQ\tLN:222\tSN:chr20\tAS:HG19\n@SQ\tLN:333\tSN:chr1\n");
217  // Verify it was added.
218  assert(strcmp(samHeader.getSQTagValue("SN", "chr1"), "chr1") == 0);
219  assert(strcmp(samHeader.getSQTagValue("LN", "chr1"), "333") == 0);
220 
221  // Test removing an SQ tag that does not exist.
222  assert(samHeader.removeSQ("chr100") == true);
223  assert(samHeader.getHeaderString(headerString) == true);
224  assert(headerString ==
225  "@SQ\tLN:222\tSN:chr20\tAS:HG19\n@SQ\tLN:333\tSN:chr1\n");
226 
227  // Remove the newly added sq2 by resetting it.
228  sq2->reset();
229  // Verify it was removed.
230  assert(samHeader.getHeaderString(headerString) == true);
231  assert(headerString == "@SQ\tLN:222\tSN:chr20\tAS:HG19\n");
232  assert(strcmp(samHeader.getSQTagValue("SN", "chr1"), "") == 0);
233  assert(strcmp(samHeader.getSQTagValue("LN", "chr1"), "") == 0);
234 
235  // Test getting HD which does exist since it was set before. Even
236  // though the VN was removed so it doesn't appear in the header string,
237  // it was never actually removed.
238  SamHeaderHD* hd = samHeader.getHD();
239  assert(hd != NULL);
240  // Blank since the sort order was never set.
241  assert(strcmp(samHeader.getTagSO(), "") == 0);
242 
243  // Set the version number.
244  assert(hd->setTag("VN", "2.1") == true);
245  // Verify it was added.
246  assert(samHeader.getHeaderString(headerString) == true);
247  assert(headerString == "@HD\tVN:2.1\n@SQ\tLN:222\tSN:chr20\tAS:HG19\n");
248  assert(strcmp(samHeader.getHDTagValue("VN"), "2.1") == 0);
249 
250  // Set the SO
251  assert(hd->setTag("SO", "coordinate") == true);
252  // Verify it was added.
253  assert(samHeader.getHeaderString(headerString) == true);
254  assert(headerString ==
255  "@HD\tVN:2.1\tSO:coordinate\n@SQ\tLN:222\tSN:chr20\tAS:HG19\n");
256  assert(strcmp(samHeader.getHDTagValue("SO"), "coordinate") == 0);
257 
258  // Reset the header.
259  samHeader.resetHeader();
260  assert(samHeader.getHeaderString(headerString) == true);
261  assert(headerString == "");
262 
263  // Add a new HD tag.
264  assert(samHeader.setHDTag("SO", "queryname") == true);
265  assert(strcmp(samHeader.getHDTagValue("SO"), "queryname") == 0);
266  assert(samHeader.getHeaderString(headerString) == true);
267  // Blank since missing VN.
268  assert(headerString == "");
269 
270  // Set the VN.
271  assert(samHeader.setHDTag("VN", "3.1") == true);
272  assert(strcmp(samHeader.getHDTagValue("SO"), "queryname") == 0);
273  assert(strcmp(samHeader.getHDTagValue("VN"), "3.1") == 0);
274  assert(samHeader.getHeaderString(headerString) == true);
275  assert(headerString == "@HD\tSO:queryname\tVN:3.1\n");
276 
277  //////////////////////////////////////////////////////////////
278  // Test removing a non-existent PG.
279  assert(samHeader.removePG("1") == true);
280  assert(samHeader.getHeaderString(headerString) == true);
281  assert(headerString == "@HD\tSO:queryname\tVN:3.1\n");
282 
283  // Test adding a null PG.
284  SamHeaderPG* pg = NULL;
285  assert(samHeader.addPG(pg) == false);
286  assert(samHeader.getHeaderString(headerString) == true);
287  assert(headerString == "@HD\tSO:queryname\tVN:3.1\n");
288 
289  // Add a PG tag.
290  assert(strcmp(samHeader.getPGTagValue("ID", "pid"), "") == 0);
291  assert(samHeader.setPGTag("ID", "pid", "pid") == true);
292  assert(strcmp(samHeader.getPGTagValue("ID", "pid"), "pid") == 0);
293  assert(samHeader.getHeaderString(headerString) == true);
294  assert(headerString == "@HD\tSO:queryname\tVN:3.1\n@PG\tID:pid\n");
295 
296  // Verify can't modify the key.
297  assert(samHeader.setPGTag("ID", "pid1", "pid") == false);
298  assert(samHeader.getHeaderString(headerString) == true);
299  assert(headerString == "@HD\tSO:queryname\tVN:3.1\n@PG\tID:pid\n");
300  assert(strcmp(samHeader.getPGTagValue("ID", "pid"), "pid") == 0);
301 
302  // Test adding a null PG.
303  pg = NULL;
304  assert(samHeader.addPG(pg) == false);
305  assert(samHeader.getHeaderString(headerString) == true);
306  assert(headerString == "@HD\tSO:queryname\tVN:3.1\n@PG\tID:pid\n");
307 
308  // Test adding a PG header when it already exists.
309  pg = new SamHeaderPG();
310  assert(pg->setTag("ID", "pid") == true);
311  assert(samHeader.addPG(pg) == false);
312  assert(samHeader.getHeaderString(headerString) == true);
313  assert(headerString == "@HD\tSO:queryname\tVN:3.1\n@PG\tID:pid\n");
314  delete pg;
315 
316  // Get a PG that does not exist.
317  pg = samHeader.getPG("pid1");
318  assert(pg == NULL);
319 
320  // Get a PG tag that does not exist.
321  assert(strcmp(samHeader.getPGTagValue("CL", "pid"), "") == 0);
322 
323  // Get the PG tag.
324  pg = samHeader.getPG("pid");
325  assert(pg != NULL);
326  assert(strcmp(pg->getTagValue("ID"), "pid") == 0);
327  // Add a tag to the PG.
328  assert(pg->setTag("VN", "pg1") == true);
329  assert(strcmp(samHeader.getPGTagValue("VN", "pid"), "pg1") == 0);
330  assert(strcmp(samHeader.getPGTagValue("ID", "pid"), "pid") == 0);
331  assert(samHeader.getHeaderString(headerString) == true);
332  assert(headerString == "@HD\tSO:queryname\tVN:3.1\n@PG\tID:pid\tVN:pg1\n");
333 
334  // Test modifying the key tag - fails.
335  assert(pg->setTag("ID", "pid1") == false);
336  assert(strcmp(samHeader.getPGTagValue("VN", "pid"), "pg1") == 0);
337  assert(strcmp(samHeader.getPGTagValue("ID", "pid"), "pid") == 0);
338  assert(samHeader.getHeaderString(headerString) == true);
339  assert(headerString == "@HD\tSO:queryname\tVN:3.1\n@PG\tID:pid\tVN:pg1\n");
340 
341  // Test modifying the VN tag.
342  assert(samHeader.setPGTag("VN", "pg", "pid") == true);
343  assert(strcmp(samHeader.getPGTagValue("VN", "pid"), "pg") == 0);
344  assert(strcmp(samHeader.getPGTagValue("ID", "pid"), "pid") == 0);
345  assert(samHeader.getHeaderString(headerString) == true);
346  assert(headerString == "@HD\tSO:queryname\tVN:3.1\n@PG\tID:pid\tVN:pg\n");
347 
348  // Test removing the VN tag.
349  assert(pg->setTag("VN", "") == true);
350  assert(strcmp(samHeader.getPGTagValue("VN", "pid"), "") == 0);
351  assert(strcmp(samHeader.getPGTagValue("ID", "pid"), "pid") == 0);
352  assert(samHeader.getHeaderString(headerString) == true);
353  assert(headerString == "@HD\tSO:queryname\tVN:3.1\n@PG\tID:pid\n");
354 
355  // Test removing a PG that does not exist.
356  assert(samHeader.removePG("pid1") == true);
357  assert(samHeader.getHeaderString(headerString) == true);
358  assert(headerString == "@HD\tSO:queryname\tVN:3.1\n@PG\tID:pid\n");
359  assert(strcmp(samHeader.getPGTagValue("VN", "pid"), "") == 0);
360  assert(strcmp(samHeader.getPGTagValue("ID", "pid"), "pid") == 0);
361 
362  // Test removing the PG.
363  assert(samHeader.removePG("pid") == true);
364  assert(samHeader.getHeaderString(headerString) == true);
365  assert(headerString == "@HD\tSO:queryname\tVN:3.1\n");
366  assert(strcmp(samHeader.getPGTagValue("VN", "pid"), "") == 0);
367  assert(strcmp(samHeader.getPGTagValue("ID", "pid"), "") == 0);
368 
369  // Test adding a PG header.
370  pg = new SamHeaderPG();
371  assert(pg->setTag("ID", "newID") == true);
372  assert(samHeader.addPG(pg) == true);
373  assert(samHeader.getHeaderString(headerString) == true);
374  assert(headerString == "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n");
375 
376  // Test adding a PG that is already there.
377  assert(samHeader.addHeaderLine("@PG\tID:newID") == false);
378  assert(samHeader.getHeaderString(headerString) == true);
379  assert(headerString == "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n");
380  // Verify it was added to the parsed header.
381  assert(strcmp(samHeader.getPGTagValue("ID", "newID"), "newID") == 0);
382 
383  // Test adding another PG header.
384  pg = new SamHeaderPG();
385  assert(pg->setTag("ID", "newID1") == true);
386  assert(samHeader.addPG(pg) == true);
387  assert(samHeader.getHeaderString(headerString) == true);
388  assert(headerString ==
389  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@PG\tID:newID1\n");
390 
391  // Test adding another PG header.
392  pg = new SamHeaderPG();
393  assert(pg->setTag("ID", "pid") == true);
394  assert(samHeader.addPG(pg) == true);
395  assert(samHeader.getHeaderString(headerString) == true);
396  assert(headerString ==
397  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@PG\tID:newID1\n@PG\tID:pid\n");
398 
399  // Test removing the new pg.
400  assert(samHeader.removePG("newID1") == true);
401  assert(samHeader.getHeaderString(headerString) == true);
402  assert(headerString ==
403  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@PG\tID:pid\n");
404 
405  // Test removing the other new pg.
406  assert(samHeader.removePG("pid") == true);
407  assert(samHeader.getHeaderString(headerString) == true);
408  assert(headerString == "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n");
409 
410  // Test adding a tag
411  assert(samHeader.setPGTag("VN", "1.0", "newID") == true);
412  assert(strcmp(samHeader.getPGTagValue("VN", "newID"), "1.0") == 0);
413  assert(strcmp(samHeader.getPGTagValue("ID", "newID"), "newID") == 0);
414  assert(samHeader.getHeaderString(headerString) == true);
415  assert(headerString ==
416  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\tVN:1.0\n");
417 
418  // Test removing a tag
419  assert(samHeader.setPGTag("VN", "", "newID") == true);
420  assert(strcmp(samHeader.getPGTagValue("VN", "newID"), "") == 0);
421  assert(strcmp(samHeader.getPGTagValue("ID", "newID"), "newID") == 0);
422  assert(samHeader.getHeaderString(headerString) == true);
423  assert(headerString == "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n");
424 
425  ////////////////////////////////////////////////////////////////////
426  // Add an SQ, but fail since LN is not specified.
427  assert(samHeader.setSQTag("AS", "HG18", "newName") == false);
428  assert(samHeader.getHeaderString(headerString) == true);
429  // SQ does not show up since it is missing the LN field.
430  assert(headerString ==
431  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n");
432  // Add the SQ's SN, but fail since LN is not specified.
433  assert(samHeader.setSQTag("SN", "newName", "newName") == false);
434  assert(samHeader.getHeaderString(headerString) == true);
435  assert(headerString ==
436  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n");
437  sq = samHeader.getSQ("newName");
438  assert(sq == NULL);
439  // Add the SQ with the LN tag.
440  assert(samHeader.setSQTag("LN", "111", "newName") == true);
441  assert(strcmp(samHeader.getSQTagValue("SN", "newName"), "newName") == 0);
442  assert(strcmp(samHeader.getSQTagValue("AS", "newName"), "") == 0);
443  assert(strcmp(samHeader.getSQTagValue("LN", "newName"), "111") == 0);
444  assert(samHeader.getHeaderString(headerString) == true);
445  assert(headerString ==
446  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\n");
447  // Add the AS.
448  assert(samHeader.setSQTag("AS", "HG18", "newName") == true);
449  assert(strcmp(samHeader.getSQTagValue("AS", "newName"), "HG18") == 0);
450  assert(strcmp(samHeader.getSQTagValue("SN", "newName"), "newName") == 0);
451  assert(strcmp(samHeader.getSQTagValue("LN", "newName"), "111") == 0);
452  assert(samHeader.getHeaderString(headerString) == true);
453  assert(headerString ==
454  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\n");
455 
456  // Get the SQ.
457  sq = samHeader.getSQ("newName");
458  assert(sq != NULL);
459  // Modify the SQ
460  assert(sq->setTag("SP", "species") == true);
461  assert(strcmp(samHeader.getSQTagValue("SN", "newName"), "newName") == 0);
462  assert(strcmp(samHeader.getSQTagValue("AS", "newName"), "HG18") == 0);
463  assert(strcmp(samHeader.getSQTagValue("LN", "newName"), "111") == 0);
464  assert(strcmp(samHeader.getSQTagValue("SP", "newName"), "species") == 0);
465  assert(samHeader.getHeaderString(headerString) == true);
466  assert(headerString ==
467  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n");
468 
469  //////////////////////////////////////////////////////////////////////
470  // Add a new RG Tag
471  assert(samHeader.setRGTag("ID", "rgID", "rgID") == true);
472  assert(samHeader.getHeaderString(headerString) == true);
473  // New RG does not show up since it is still missing a required field.
474  assert(headerString ==
475  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n");
476  assert(strcmp(samHeader.getRGTagValue("ID", "rgID"), "rgID") == 0);
477 
478  // Add the missing SM field.
479  assert(samHeader.setRGTag("SM", "sm1", "rgID") == true);
480  assert(samHeader.getHeaderString(headerString) == true);
481  assert(headerString ==
482  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n");
483  assert(strcmp(samHeader.getRGTagValue("ID", "rgID"), "rgID") == 0);
484 
485  // Verify can't modify the key.
486  assert(samHeader.setRGTag("ID", "rgID1", "rgID") == false);
487  assert(samHeader.getHeaderString(headerString) == true);
488  assert(headerString ==
489  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n");
490  assert(strcmp(samHeader.getRGTagValue("ID", "rgID"), "rgID") == 0);
491 
492  // Verify that the copied header did not change.
493  assert(newHeader.getHeaderString(headerString) == true);
494  assert(headerString == "@HD\tVN:1.0\n@SQ\tLN:123\tSN:chr20\n");
495  // Verify it was added to the parsed header.
496  assert(strcmp(newHeader.getSQTagValue("LN", "chr20"), "123") == 0);
497 
498  // Add a new RG Tag
499  assert(samHeader.setRGTag("SM", "sample1", "rgID1") == true);
500  assert(samHeader.getHeaderString(headerString) == true);
501  // String does not show the tag until all required fields are there.
502  assert(headerString ==
503  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample1\n");
504  assert(strcmp(samHeader.getRGTagValue("ID", "rgID1"), "rgID1") == 0);
505  assert(strcmp(samHeader.getRGTagValue("SM", "rgID1"), "sample1") == 0);
506 
507  // Modify an RG tag.
508  assert(samHeader.setRGTag("SM", "sample", "rgID1") == true);
509  assert(samHeader.getHeaderString(headerString) == true);
510  assert(headerString ==
511  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample\n");
512  assert(strcmp(samHeader.getRGTagValue("ID", "rgID1"), "rgID1") == 0);
513  assert(strcmp(samHeader.getRGTagValue("SM", "rgID1"), "sample") == 0);
514 
515  // Test removing an rg that does not exist.
516  assert(samHeader.removeRG("rgID2") == true);
517  assert(samHeader.getHeaderString(headerString) == true);
518  assert(headerString ==
519  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample\n");
520 
521  // Create a new RG, set some values and add it.
522  SamHeaderRG* rg = new SamHeaderRG();
523  // Try adding it without a key.
524  assert(samHeader.addRG(rg) == false);
525  assert(samHeader.getHeaderString(headerString) == true);
526  assert(headerString ==
527  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample\n");
528  // Set some values in rg.
529  assert(rg->setTag("ID", "rgID2") == true);
530  assert(rg->setTag("SM", "sm2") == true);
531  assert(samHeader.getHeaderString(headerString) == true);
532  assert(headerString ==
533  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample\n");
534  // Add the new RG.
535  assert(samHeader.addRG(rg) == true);
536  assert(samHeader.getHeaderString(headerString) == true);
537  assert(headerString ==
538  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample\n@RG\tID:rgID2\tSM:sm2\n");
539  assert(strcmp(samHeader.getRGTagValue("ID", "rgID2"), "rgID2") == 0);
540 
541  // Test trying to add another one with the same key.
542  rg = new SamHeaderRG();
543  assert(rg->setTag("ID", "rgID2") == true);
544  assert(samHeader.addRG(rg) == false);
545  assert(samHeader.getHeaderString(headerString) == true);
546  assert(headerString ==
547  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample\n@RG\tID:rgID2\tSM:sm2\n");
548 
549 
550  // Test removing the rg again.
551  assert(samHeader.removeRG("rgID2") == true);
552  assert(samHeader.getHeaderString(headerString) == true);
553  assert(headerString ==
554  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample\n");
555 
556  // Test getting an rg tag that doesn't exist
557  assert(strcmp(samHeader.getRGTagValue("DS", "rgID"), "") == 0);
558  assert(samHeader.getHeaderString(headerString) == true);
559  assert(headerString ==
560  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample\n");
561 
562  // Test getting an rg tag from a removed key
563  assert(strcmp(samHeader.getRGTagValue("ID", "rgID2"), "") == 0);
564  assert(samHeader.getHeaderString(headerString) == true);
565  assert(headerString ==
566  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample\n");
567 
568  // Test getting an rg tag from an key that doesn't exist
569  assert(strcmp(samHeader.getRGTagValue("ID", "rgID22"), "") == 0);
570  assert(samHeader.getHeaderString(headerString) == true);
571  assert(headerString ==
572  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample\n");
573 
574  // Test adding a null header.
575  rg = NULL;
576  assert(samHeader.addRG(rg) == false);
577  assert(samHeader.getHeaderString(headerString) == true);
578  assert(headerString ==
579  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample\n");
580 
581  // Test adding the deleted header back in.
582  rg = new SamHeaderRG();
583  assert(rg->setTag("ID", "rgID2") == true);
584  assert(rg->setTag("SM", "sm2") == true);
585  assert(samHeader.addRG(rg) == true);
586  assert(samHeader.getHeaderString(headerString) == true);
587  assert(headerString ==
588  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample\n@RG\tID:rgID2\tSM:sm2\n");
589 
590  // Test adding an RG that is already there.
591  assert(samHeader.addHeaderLine("@RG\tID:rgID\tSM:sm5") == false);
592  assert(samHeader.getHeaderString(headerString) == true);
593  assert(headerString == "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample\n@RG\tID:rgID2\tSM:sm2\n");
594  // Verify it was added to the parsed header.
595  assert(strcmp(samHeader.getRGTagValue("SM", "rgID"), "sm1") == 0);
596 
597 
598  // Get an RG record then modify it.
599  rg = samHeader.getRG("rgID1");
600  assert(rg != NULL);
601  assert(rg->setTag("SM", "sample1") == true);
602  assert(samHeader.getHeaderString(headerString) == true);
603  assert(headerString ==
604  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample1\n@RG\tID:rgID2\tSM:sm2\n");
605 
606  // Try to modify the key.
607  assert(rg->setTag("ID", "rgID111") == false);
608  assert(samHeader.getHeaderString(headerString) == true);
609  assert(headerString ==
610  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample1\n@RG\tID:rgID2\tSM:sm2\n");
611 
612  ////////////////////////////////////////////////////////////////////////////
613  // Test getting a comment when there aren't any.
614  assert(strcmp(samHeader.getNextComment(), "") == 0);
615  assert(samHeader.getHeaderString(headerString) == true);
616  assert(headerString ==
617  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample1\n@RG\tID:rgID2\tSM:sm2\n");
618 
619  // Test getting each headerline when there are no comments.
620  const char* hdrlinechar;
621  std::string hdrline;
622  assert(samHeader.getNextHeaderLine(hdrline));
623  hdrlinechar = hdrline.c_str();
624  // Test to make sure there is not memory corruption.
625  std::string tmpString = "@SQ\tSN:queryname\tVN:3.1\n";
626  assert(hdrline == "@HD\tSO:queryname\tVN:3.1\n");
627  assert(strcmp(hdrlinechar,
628  "@HD\tSO:queryname\tVN:3.1\n") == 0);
629 
630  assert(samHeader.getNextHeaderLine(hdrline));
631  assert(hdrline == "@PG\tID:newID\n");
632  assert(samHeader.getNextHeaderLine(hdrline));
633  assert(hdrline == "@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n");
634  assert(samHeader.getNextHeaderLine(hdrline));
635  assert(hdrline == "@RG\tID:rgID\tSM:sm1\n");
636  assert(samHeader.getNextHeaderLine(hdrline));
637  assert(hdrline == "@RG\tID:rgID1\tSM:sample1\n");
638  assert(samHeader.getNextHeaderLine(hdrline));
639  assert(hdrline == "@RG\tID:rgID2\tSM:sm2\n");
640  assert(!samHeader.getNextHeaderLine(hdrline));
641  assert(hdrline == "");
642  assert(!samHeader.getNextHeaderLine(hdrline));
643  assert(hdrline == "");
644  assert(samHeader.getHeaderString(headerString) == true);
645  assert(headerString ==
646  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample1\n@RG\tID:rgID2\tSM:sm2\n");
647 
648  // Verify that getHeaderRecord returns nothing.
649  assert(samHeader.getNextHeaderRecord() == NULL);
650 
651  // Reset the header record iter.
652  samHeader.resetHeaderRecordIter();
653 
654  // Test getting each headerrecord when there are no comments.
655  SamHeaderRecord* hdrRec = samHeader.getNextHeaderRecord();
656  assert(hdrRec != NULL);
657  assert(strcmp(hdrRec->getTypeString(), "HD") == 0);
658  assert(hdrRec->getType() == SamHeaderRecord::HD);
659  assert(strcmp(hdrRec->getTagValue("SO"), "queryname") == 0);
660  assert(strcmp(hdrRec->getTagValue("VN"), "3.1") == 0);
661  hdrRec = samHeader.getNextHeaderRecord();
662  assert(hdrRec != NULL);
663  assert(strcmp(hdrRec->getTypeString(), "PG") == 0);
664  assert(hdrRec->getType() == SamHeaderRecord::PG);
665  assert(strcmp(hdrRec->getTagValue("ID"), "newID") == 0);
666  hdrRec = samHeader.getNextHeaderRecord();
667  assert(hdrRec != NULL);
668  assert(strcmp(hdrRec->getTypeString(), "SQ") == 0);
669  assert(hdrRec->getType() == SamHeaderRecord::SQ);
670  assert(strcmp(hdrRec->getTagValue("SN"), "newName") == 0);
671  assert(strcmp(hdrRec->getTagValue("AS"), "HG18") == 0);
672  assert(strcmp(hdrRec->getTagValue("LN"), "111") == 0);
673  hdrRec = samHeader.getNextHeaderRecord();
674  assert(hdrRec != NULL);
675  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
676  assert(hdrRec->getType() == SamHeaderRecord::RG);
677  assert(strcmp(hdrRec->getTagValue("ID"), "rgID") == 0);
678  assert(strcmp(hdrRec->getTagValue("SM"), "sm1") == 0);
679 
680  // Get the SQ Header Record (should have no affect on the general
681  // getNextHeaderRecord calls).
682  hdrRec = samHeader.getNextSQRecord();
683  assert(hdrRec != NULL);
684  assert(strcmp(hdrRec->getTypeString(), "SQ") == 0);
685  assert(hdrRec->getType() == SamHeaderRecord::SQ);
686  assert(strcmp(hdrRec->getTagValue("SN"), "newName") == 0);
687  assert(strcmp(hdrRec->getTagValue("AS"), "HG18") == 0);
688  assert(strcmp(hdrRec->getTagValue("LN"), "111") == 0);
689  // Only one SQ Header Record.
690  hdrRec = samHeader.getNextSQRecord();
691  assert(hdrRec == NULL);
692 
693  // Get the RG/PG Header Records (should have no affect on the general
694  // getNextHeaderRecord calls).
695  hdrRec = samHeader.getNextRGRecord();
696  assert(hdrRec != NULL);
697  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
698  assert(hdrRec->getType() == SamHeaderRecord::RG);
699  assert(strcmp(hdrRec->getTagValue("ID"), "rgID") == 0);
700  assert(strcmp(hdrRec->getTagValue("SM"), "sm1") == 0);
701  // Get the next RG record.
702  hdrRec = samHeader.getNextRGRecord();
703  assert(hdrRec != NULL);
704  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
705  assert(hdrRec->getType() == SamHeaderRecord::RG);
706  assert(strcmp(hdrRec->getTagValue("ID"), "rgID1") == 0);
707  assert(strcmp(hdrRec->getTagValue("SM"), "sample1") == 0);
708  // Get the PG record.
709  hdrRec = samHeader.getNextPGRecord();
710  assert(hdrRec != NULL);
711  assert(strcmp(hdrRec->getTypeString(), "PG") == 0);
712  assert(hdrRec->getType() == SamHeaderRecord::PG);
713  assert(strcmp(hdrRec->getTagValue("ID"), "newID") == 0);
714  // Get the last RG record.
715  hdrRec = samHeader.getNextRGRecord();
716  assert(hdrRec != NULL);
717  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
718  assert(hdrRec->getType() == SamHeaderRecord::RG);
719  assert(strcmp(hdrRec->getTagValue("ID"), "rgID2") == 0);
720  assert(strcmp(hdrRec->getTagValue("SM"), "sm2") == 0);
721  // Already got all RG Records.
722  hdrRec = samHeader.getNextRGRecord();
723  assert(hdrRec == NULL);
724  // Reset the RG record.
725  samHeader.resetRGRecordIter();
726  // Get the RG record.
727  hdrRec = samHeader.getNextRGRecord();
728  assert(hdrRec != NULL);
729  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
730  assert(hdrRec->getType() == SamHeaderRecord::RG);
731  assert(strcmp(hdrRec->getTagValue("ID"), "rgID") == 0);
732  assert(strcmp(hdrRec->getTagValue("SM"), "sm1") == 0);
733  // No more PG records.
734  hdrRec = samHeader.getNextPGRecord();
735  assert(hdrRec == NULL);
736  // No more SQ records.
737  hdrRec = samHeader.getNextSQRecord();
738  assert(hdrRec == NULL);
739  // Reset the SQ record iterator.
740  samHeader.resetSQRecordIter();
741  // No more PG records.
742  hdrRec = samHeader.getNextPGRecord();
743  assert(hdrRec == NULL);
744  // Get the now reset SQ record.
745  hdrRec = samHeader.getNextSQRecord();
746  assert(hdrRec != NULL);
747  assert(strcmp(hdrRec->getTypeString(), "SQ") == 0);
748  assert(hdrRec->getType() == SamHeaderRecord::SQ);
749  assert(strcmp(hdrRec->getTagValue("SN"), "newName") == 0);
750  assert(strcmp(hdrRec->getTagValue("AS"), "HG18") == 0);
751  assert(strcmp(hdrRec->getTagValue("LN"), "111") == 0);
752  // Only one SQ Header Record.
753  hdrRec = samHeader.getNextSQRecord();
754  assert(hdrRec == NULL);
755  // Reset the PG record iterator.
756  samHeader.resetPGRecordIter();
757  // No more SQ records.
758  hdrRec = samHeader.getNextSQRecord();
759  assert(hdrRec == NULL);
760  // Get the next RG record.
761  hdrRec = samHeader.getNextRGRecord();
762  assert(hdrRec != NULL);
763  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
764  assert(hdrRec->getType() == SamHeaderRecord::RG);
765  assert(strcmp(hdrRec->getTagValue("ID"), "rgID1") == 0);
766  assert(strcmp(hdrRec->getTagValue("SM"), "sample1") == 0);
767  // Get the PG record.
768  hdrRec = samHeader.getNextPGRecord();
769  assert(hdrRec != NULL);
770  assert(strcmp(hdrRec->getTypeString(), "PG") == 0);
771  assert(hdrRec->getType() == SamHeaderRecord::PG);
772  assert(strcmp(hdrRec->getTagValue("ID"), "newID") == 0);
773 
774 
775  hdrRec = samHeader.getNextHeaderRecord();
776  assert(hdrRec != NULL);
777  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
778  assert(hdrRec->getType() == SamHeaderRecord::RG);
779  assert(strcmp(hdrRec->getTagValue("ID"), "rgID1") == 0);
780  assert(strcmp(hdrRec->getTagValue("SM"), "sample1") == 0);
781  hdrRec = samHeader.getNextHeaderRecord();
782  assert(hdrRec != NULL);
783  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
784  assert(hdrRec->getType() == SamHeaderRecord::RG);
785  assert(strcmp(hdrRec->getTagValue("ID"), "rgID2") == 0);
786  assert(strcmp(hdrRec->getTagValue("SM"), "sm2") == 0);
787  hdrRec = samHeader.getNextHeaderRecord();
788  assert(hdrRec == NULL);
789  hdrRec = samHeader.getNextHeaderRecord();
790  assert(hdrRec == NULL);
791  assert(!samHeader.getNextHeaderLine(hdrline));
792  assert(hdrline == "");
793  assert(!samHeader.getNextHeaderLine(hdrline));
794  assert(hdrline == "");
795 
796  assert(samHeader.getHeaderString(headerString) == true);
797  assert(headerString ==
798  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample1\n@RG\tID:rgID2\tSM:sm2\n");
799 
800  // Add some comments.
801  assert(samHeader.addComment("My Comment") == true);
802  assert(samHeader.getHeaderString(headerString) == true);
803  assert(headerString ==
804  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample1\n@RG\tID:rgID2\tSM:sm2\n@CO\tMy Comment\n");
805 
806  // Call getNextHeaderRecord - still nothing.
807  hdrRec = samHeader.getNextHeaderRecord();
808  assert(hdrRec == NULL);
809 
810  // Call getNextHeaderLine - should return the comment.
811  assert(samHeader.getNextHeaderLine(hdrline));
812  assert(hdrline == "@CO\tMy Comment\n");
813  assert(!samHeader.getNextHeaderLine(hdrline));
814  assert(hdrline == "");
815  assert(!samHeader.getNextHeaderLine(hdrline));
816  assert(hdrline == "");
817 
818  // Call getNextCommentLine - should return the comment.
819  assert(strcmp(samHeader.getNextComment(), "My Comment") == 0);
820  assert(strcmp(samHeader.getNextComment(), "") == 0);
821  assert(strcmp(samHeader.getNextComment(), "") == 0);
822 
823  // Add another comment.
824  assert(samHeader.addComment("My Comment2") == true);
825  assert(samHeader.getHeaderString(headerString) == true);
826  assert(headerString ==
827  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample1\n@RG\tID:rgID2\tSM:sm2\n@CO\tMy Comment\n@CO\tMy Comment2\n");
828 
829  newHeader = samHeader;
830  assert(newHeader.getHeaderString(headerString) == true);
831  assert(headerString ==
832  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample1\n@RG\tID:rgID2\tSM:sm2\n@CO\tMy Comment\n@CO\tMy Comment2\n");
833 
834  // Call getNextHeaderLine - should return the comment.
835  assert(samHeader.getNextHeaderLine(hdrline));
836  assert(hdrline == "@CO\tMy Comment2\n");
837  assert(!samHeader.getNextHeaderLine(hdrline));
838  assert(hdrline == "");
839  assert(!samHeader.getNextHeaderLine(hdrline));
840  assert(hdrline == "");
841 
842  // Call getNextCommentLine - should return the comment.
843  assert(strcmp(samHeader.getNextComment(), "My Comment2") == 0);
844  assert(strcmp(samHeader.getNextComment(), "") == 0);
845  assert(strcmp(samHeader.getNextComment(), "") == 0);
846 
847  // Reset the header record iter.
848  samHeader.resetHeaderRecordIter();
849 
850  // Recall getNextCommentLine - should not return anything.
851  assert(strcmp(samHeader.getNextComment(), "") == 0);
852  assert(strcmp(samHeader.getNextComment(), "") == 0);
853 
854  // Reset the next comment iter.
855  samHeader.resetCommentIter();
856 
857  // Call the get next headerLine, record, comment interspersed with
858  // each other.
859  hdrRec = samHeader.getNextHeaderRecord();
860  assert(hdrRec != NULL);
861  assert(strcmp(hdrRec->getTypeString(), "HD") == 0);
862  assert(hdrRec->getType() == SamHeaderRecord::HD);
863  assert(strcmp(hdrRec->getTagValue("SO"), "queryname") == 0);
864  assert(strcmp(hdrRec->getTagValue("VN"), "3.1") == 0);
865  assert(samHeader.getNextHeaderLine(hdrline));
866  assert(hdrline == "@PG\tID:newID\n");
867  assert(samHeader.getNextHeaderLine(hdrline));
868  assert(hdrline == "@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n");
869  hdrRec = samHeader.getNextHeaderRecord();
870  assert(hdrRec != NULL);
871  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
872  assert(hdrRec->getType() == SamHeaderRecord::RG);
873  assert(strcmp(hdrRec->getTagValue("ID"), "rgID") == 0);
874  hdrRec = samHeader.getNextHeaderRecord();
875  assert(hdrRec != NULL);
876  assert(strcmp(samHeader.getNextComment(), "My Comment") == 0);
877  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
878  assert(hdrRec->getType() == SamHeaderRecord::RG);
879  assert(strcmp(hdrRec->getTagValue("ID"), "rgID1") == 0);
880  assert(strcmp(hdrRec->getTagValue("SM"), "sample1") == 0);
881  assert(samHeader.getNextHeaderLine(hdrline));
882  assert(hdrline == "@RG\tID:rgID2\tSM:sm2\n");
883  hdrRec = samHeader.getNextHeaderRecord();
884  assert(hdrRec == NULL);
885  assert(samHeader.getNextHeaderLine(hdrline));
886  assert(hdrline == "@CO\tMy Comment\n");
887  hdrRec = samHeader.getNextHeaderRecord();
888  assert(hdrRec == NULL);
889  assert(samHeader.getNextHeaderLine(hdrline));
890  assert(hdrline == "@CO\tMy Comment2\n");
891  assert(!samHeader.getNextHeaderLine(hdrline));
892  assert(hdrline == "");
893  assert(strcmp(samHeader.getNextComment(), "My Comment2") == 0);
894  assert(!samHeader.getNextHeaderLine(hdrline));
895  assert(hdrline == "");
896  hdrRec = samHeader.getNextHeaderRecord();
897  assert(hdrRec == NULL);
898  assert(strcmp(samHeader.getNextComment(), "") == 0);
899  assert(strcmp(samHeader.getNextComment(), "") == 0);
900 
901  samOut.WriteHeader(samHeader);
902 
903  // Reset the header.
904  samHeader.resetHeader();
905  assert(samHeader.getHeaderString(headerString) == true);
906  assert(headerString == "");
907  assert(!samHeader.getNextHeaderLine(hdrline));
908  assert(hdrline == "");
909  assert(strcmp(samHeader.getHDTagValue("SO"), "") == 0);
910  assert(strcmp(samHeader.getHDTagValue("VN"), "") == 0);
911 
912  // Try adding a key to the HD tag.
913  hd = new SamHeaderHD();
914  assert(hd->addKey("3.1") == false);
915  assert(strcmp(hd->getTagValue("VN"), "") == 0);
916  assert(hd->isActiveHeaderRecord() == false);
917 
918  assert(hd->setTag("VN", "3.1") == true);
919  assert(hd->isActiveHeaderRecord() == true);
920  assert(strcmp(hd->getTagValue("VN"), "3.1") == 0);
921 
922  // Verify the copied header did not change.
923  assert(newHeader.getHeaderString(headerString) == true);
924  assert(headerString ==
925  "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n@RG\tID:rgID\tSM:sm1\n@RG\tID:rgID1\tSM:sample1\n@RG\tID:rgID2\tSM:sm2\n@CO\tMy Comment\n@CO\tMy Comment2\n");
926  // Verify it was added to the parsed header.
927  assert(strcmp(newHeader.getSQTagValue("LN", "chr20"), "") == 0);
928 }
929 
930 
931 void testWriteCopiedHeader(const char* fileName)
932 {
933  SamFile samIn;
934  assert(samIn.OpenForRead(fileName));
935 
936  SamFile samOut;
937  assert(samOut.OpenForWrite("results/MyTestOut2.bam"));
938  SamFile samOut2;
939  assert(samOut2.OpenForWrite("results/MyTestOut2.sam"));
940 
941  // Read the sam header.
942  SamFileHeader samHeader;
943  assert(samIn.ReadHeader(samHeader));
944  validateHeader(samHeader);
945 
946  SamFileHeader newHeader;
947 
948  std::string hdrLine;
949  assert(samHeader.getNextHeaderLine(hdrLine));
950  newHeader.addHeaderLine("@HD\tVN:1.02");
951  bool hdrStatus = true;
952  while(hdrStatus)
953  {
954  newHeader.addHeaderLine(hdrLine.c_str());
955  hdrStatus = samHeader.getNextHeaderLine(hdrLine);
956  }
957 
958  // Write the sam header.
959  assert(samOut.WriteHeader(newHeader));
960  assert(samOut2.WriteHeader(newHeader));
961 
962  SamRecord samRecord;
963 
964  // Keep reading records until ReadRecord returns false.
965  while(samIn.ReadRecord(samHeader, samRecord))
966  {
967  // Successfully read a record from the file, so write it.
968  assert(samOut.WriteRecord(newHeader, samRecord));
969  assert(samOut2.WriteRecord(newHeader, samRecord));
970  }
971 
972  assert(samIn.GetStatus() == SamStatus::NO_MORE_RECS);
973 
974  // Close the output files.
975  samOut.Close();
976  samOut2.Close();
977 
978  SamFileReader bamRead("results/MyTestOut2.bam");
979  SamFileReader samRead("results/MyTestOut2.sam");
980 
981  // Read and check the header.
982  assert(samRead.ReadHeader(samHeader));
983  validateHeaderFields(samHeader);
984  std::string headerString = "";
985  assert(samHeader.getHeaderString(headerString) == true);
986  assert(headerString == "@HD\tVN:1.02\n@SQ\tSN:1\tLN:247249719\n@SQ\tSN:2\tLN:242951149\n@SQ\tSN:3\tLN:199501827\n@SQ\tSN:4\tLN:191273063\n@SQ\tSN:5\tLN:180857866\n@SQ\tSN:6\tLN:170899992\n@SQ\tSN:7\tLN:158821424\n@SQ\tSN:8\tLN:146274826\n@SQ\tSN:9\tLN:140273252\n@SQ\tSN:10\tLN:135374737\n@SQ\tSN:11\tLN:134452384\n@SQ\tSN:12\tLN:132349534\n@SQ\tSN:13\tLN:114142980\n@SQ\tSN:14\tLN:106368585\n@SQ\tSN:15\tLN:100338915\n@SQ\tSN:16\tLN:88827254\n@SQ\tSN:17\tLN:78774742\n@SQ\tSN:18\tLN:76117153\n@SQ\tSN:19\tLN:63811651\n@SQ\tSN:20\tLN:62435964\n@SQ\tSN:21\tLN:46944323\n@SQ\tSN:22\tLN:49691432\n@SQ\tSN:X\tLN:154913754\n@RG\tID:myID\tLB:library\tSM:sample\n@RG\tID:myID2\tSM:sample2\tLB:library2\n@CO\tComment 1\n@CO\tComment 2\n");
987 
988  assert(bamRead.ReadHeader(samHeader));
989  validateHeaderFields(samHeader);
990  headerString = "";
991  assert(samHeader.getHeaderString(headerString) == true);
992  assert(headerString == "@HD\tVN:1.02\n@SQ\tSN:1\tLN:247249719\n@SQ\tSN:2\tLN:242951149\n@SQ\tSN:3\tLN:199501827\n@SQ\tSN:4\tLN:191273063\n@SQ\tSN:5\tLN:180857866\n@SQ\tSN:6\tLN:170899992\n@SQ\tSN:7\tLN:158821424\n@SQ\tSN:8\tLN:146274826\n@SQ\tSN:9\tLN:140273252\n@SQ\tSN:10\tLN:135374737\n@SQ\tSN:11\tLN:134452384\n@SQ\tSN:12\tLN:132349534\n@SQ\tSN:13\tLN:114142980\n@SQ\tSN:14\tLN:106368585\n@SQ\tSN:15\tLN:100338915\n@SQ\tSN:16\tLN:88827254\n@SQ\tSN:17\tLN:78774742\n@SQ\tSN:18\tLN:76117153\n@SQ\tSN:19\tLN:63811651\n@SQ\tSN:20\tLN:62435964\n@SQ\tSN:21\tLN:46944323\n@SQ\tSN:22\tLN:49691432\n@SQ\tSN:X\tLN:154913754\n@RG\tID:myID\tLB:library\tSM:sample\n@RG\tID:myID2\tSM:sample2\tLB:library2\n@CO\tComment 1\n@CO\tComment 2\n");
993 
994  assert(samHeader.getNextHeaderLine(hdrLine));
995  std::string expectedString = "@HD\tVN:1.02\n";
996 
997  assert(expectedString == hdrLine);
998 
999 
1000  // TODO - validate reading these written records back in.
1001 
1002 }
1003 
SamFileHeader::getRGTagValue
const char * getRGTagValue(const char *tag, const char *id)
Get the value associated with the specified tag on the RG line with the specified read group identifi...
Definition: SamFileHeader.cpp:714
SamFileHeader::getHD
SamHeaderHD * getHD()
Get the HD object, returning NULL if there is no HD record.
Definition: SamFileHeader.cpp:768
SamFileHeader::getTagSO
const char * getTagSO()
DEPRECATED.
Definition: SamFileHeader.cpp:809
SamFileHeader::resetCommentIter
void resetCommentIter()
Resets to the beginning of the comments so getNextComment returns the first comment.
Definition: SamFileHeader.cpp:998
SamHeaderRecord::isActiveHeaderRecord
bool isActiveHeaderRecord()
This record is active (true) if there is at least one tag set.
Definition: SamHeaderRecord.cpp:301
SamFileHeader::removePG
bool removePG(const char *id)
Remove PG record with the specified key.
Definition: SamFileHeader.cpp:647
SamHeaderRecord::getTagValue
const char * getTagValue(const char *tag) const
Return the value associated with the specified tag.
Definition: SamHeaderRecord.cpp:100
SamFileHeader::resetPGRecordIter
void resetPGRecordIter()
Reset to the beginning of the header records so the next call to getNextPGRecord returns the first PG...
Definition: SamFileHeader.cpp:860
SamFile::WriteRecord
bool WriteRecord(SamFileHeader &header, SamRecord &record)
Writes the specified record into the file.
Definition: SamFile.cpp:619
SamFileHeader::getPG
SamHeaderPG * getPG(const char *id)
Get the PG object with the specified id, returning NULL if there is no PG object with that key.
Definition: SamFileHeader.cpp:789
SamHeaderRecord::PG
@ PG
Program.
Definition: SamHeaderRecord.h:35
SamFileHeader::resetRGRecordIter
void resetRGRecordIter()
Reset to the beginning of the header records so the next call to getNextRGRecord returns the first RG...
Definition: SamFileHeader.cpp:852
SamFileHeader::setHDTag
bool setHDTag(const char *tag, const char *value)
Set the specified tag to the specified value in the HD header, remove the tag by specifying value="".
Definition: SamFileHeader.cpp:225
StatGenStatus::NO_MORE_RECS
@ NO_MORE_RECS
NO_MORE_RECS: failed to read a record since there are no more to read either in the file or section i...
Definition: StatGenStatus.h:36
SamFile::GetStatus
SamStatus::Status GetStatus()
Get the Status of the last call that sets status.
Definition: SamFile.h:207
SamFileHeader::getSQTagValue
const char * getSQTagValue(const char *tag, const char *name)
Get the value associated with the specified tag on the SQ line with the specified sequence name,...
Definition: SamFileHeader.cpp:696
SamHeaderRecord::getTypeString
const char * getTypeString()
Return the type of this header record (HD, SQ, RG, or PG) as a string.
Definition: SamHeaderRecord.cpp:308
SamHeaderSQ
Definition: SamHeaderSQ.h:23
SamFileHeader::addSQ
bool addSQ(SamHeaderSQ *sq)
Add the SQ record to the header.
Definition: SamFileHeader.cpp:415
SamFileHeader::resetHeader
void resetHeader()
Initialize the header.
Definition: SamFileHeader.cpp:90
SamFile::ReadRecord
bool ReadRecord(SamFileHeader &header, SamRecord &record)
Reads the next record from the file & stores it in the passed in record.
Definition: SamFile.cpp:501
SamHeaderRG
Definition: SamHeaderRG.h:23
SamFileHeader::getNextComment
const char * getNextComment()
Returns the comment on the next comment line.
Definition: SamFileHeader.cpp:985
SamHeaderRecord::SQ
@ SQ
Sequence Dictionary.
Definition: SamHeaderRecord.h:33
SamFileHeader::getSQ
SamHeaderSQ * getSQ(const char *name)
Get the SQ object with the specified sequence name, returning NULL if there is no SQ object with that...
Definition: SamFileHeader.cpp:775
SamFileHeader::resetHeaderRecordIter
void resetHeaderRecordIter()
Reset to the beginning of the header records so the next call to getNextHeaderRecord returns the firs...
Definition: SamFileHeader.cpp:966
SamFileHeader::getHDTagValue
const char * getHDTagValue(const char *tag)
Returns the value associated with the specified HD tag, returning "" if the tag does not exist in the...
Definition: SamFileHeader.cpp:683
SamHeaderRecord::HD
@ HD
Header.
Definition: SamHeaderRecord.h:32
SamFileHeader::copy
bool copy(const SamFileHeader &header)
Copy method copies the passed in header into this header.
Definition: SamFileHeader.cpp:59
SamHeaderPG
Definition: SamHeaderPG.h:24
SamFileHeader::getHeaderString
bool getHeaderString(std::string &header) const
Set the passed in string to the entire header string, clearing its current contents.
Definition: SamFileHeader.cpp:131
SamHeaderRecord::RG
@ RG
Read Group.
Definition: SamHeaderRecord.h:34
SamFile::OpenForWrite
bool OpenForWrite(const char *filename, SamFileHeader *header=NULL)
Open a sam/bam file for writing with the specified filename, determining SAM/BAM from the extension (...
Definition: SamFile.cpp:223
SamFileHeader::removeSQ
bool removeSQ(const char *name)
Remove SQ record with the specified key.
Definition: SamFileHeader.cpp:573
SamFileHeader::getPGTagValue
const char * getPGTagValue(const char *tag, const char *id)
Get the value associated with the specified tag on the RG line with the specified id,...
Definition: SamFileHeader.cpp:730
SamFileHeader::addRG
bool addRG(SamHeaderRG *rg)
Add the RG record to the header.
Definition: SamFileHeader.cpp:458
SamFileHeader::setPGTag
bool setPGTag(const char *tag, const char *value, const char *id)
Set the specified tag to the specified value in the PG header with the specified id,...
Definition: SamFileHeader.cpp:353
SamFileHeader::resetSQRecordIter
void resetSQRecordIter()
Reset to the beginning of the header records so the next call to getNextSQRecord returns the first SQ...
Definition: SamFileHeader.cpp:844
SamHeaderRecord::addKey
bool addKey(const char *value)
Add the key tag with the specified value (not for HD headers).
Definition: SamHeaderRecord.cpp:273
SamFileHeader::addPG
bool addPG(SamHeaderPG *pg)
Add the PG record to the header.
Definition: SamFileHeader.cpp:492
SamFileHeader::getNextHeaderRecord
SamHeaderRecord * getNextHeaderRecord(uint32_t &index, SamHeaderRecord::SamHeaderRecordType headerType)
Get the next header record of the specified type starting from the specified index and update the ind...
Definition: SamFileHeader.cpp:871
SamFileHeader::setSQTag
bool setSQTag(const char *tag, const char *value, const char *name)
Set the specified tag to the specified value in the SQ header with the specified name,...
Definition: SamFileHeader.cpp:252
SamFileHeader::getNextPGRecord
SamHeaderRecord * getNextPGRecord()
Get the next PG header record.
Definition: SamFileHeader.cpp:835
SamFileHeader
This class allows a user to get/set the fields in a SAM/BAM Header.
Definition: SamFileHeader.h:34
SamFileHeader::getNextRGRecord
SamHeaderRecord * getNextRGRecord()
Get the next RG header record.
Definition: SamFileHeader.cpp:826
SamRecord
Class providing an easy to use interface to get/set/operate on the fields in a SAM/BAM record.
Definition: SamRecord.h:51
SamFile::OpenForRead
bool OpenForRead(const char *filename, SamFileHeader *header=NULL)
Open a sam/bam file for reading with the specified filename, determing the type of file and SAM/BAM b...
Definition: SamFile.cpp:93
SamFile::WriteHeader
bool WriteHeader(SamFileHeader &header)
Writes the specified header into the file.
Definition: SamFile.cpp:467
SamFile::ReadHeader
bool ReadHeader(SamFileHeader &header)
Reads the header section from the file and stores it in the passed in header.
Definition: SamFile.cpp:437
SamFileHeader::getRG
SamHeaderRG * getRG(const char *id)
Get the RG object with the specified read group identifier, returning NULL if there is no RG object w...
Definition: SamFileHeader.cpp:782
SamFileHeader::removeRG
bool removeRG(const char *id)
Remove RG record with the specified key.
Definition: SamFileHeader.cpp:610
SamFile::Close
void Close()
Close the file if there is one open.
Definition: SamFile.cpp:400
SamFileHeader::getNextHeaderLine
bool getNextHeaderLine(std::string &headerLine)
Set the passed in string to the next header line, overwritting the passed in string.
Definition: SamFileHeader.cpp:941
SamFile
Allows the user to easily read/write a SAM/BAM file.
Definition: SamFile.h:35
SamHeaderRecord::reset
void reset()
Reset this header record to an empty state with no tags.
Definition: SamHeaderRecord.cpp:212
SamHeaderRecord::getType
SamHeaderRecordType getType()
Return the type of this header record (HD, SQ, RG, or PG) as an enum.
Definition: SamHeaderRecord.cpp:315
SamHeaderRecord
This class encapsulates the tag value pairs contained with a SAM Header line with accessors for getti...
Definition: SamHeaderRecord.h:27
SamFileHeader::addHeaderLine
bool addHeaderLine(const char *type, const char *tag, const char *value)
Add a header line that is just one tag with a const char* value.
Definition: SamFileHeader.cpp:180
SamHeaderRecord::setTag
bool setTag(const char *tag, const char *value)
Set the value of the specified tag to the specified value, deletes the tag when value is NULL.
Definition: SamHeaderRecord.cpp:119
SamHeaderHD
Definition: SamHeaderHD.h:23
SamFileReader
Child class of SamFile for reading files.
Definition: SamFile.h:455
SamFileHeader::getNextSQRecord
SamHeaderRecord * getNextSQRecord()
Get the next SQ header record.
Definition: SamFileHeader.cpp:817
SamFileHeader::setRGTag
bool setRGTag(const char *tag, const char *value, const char *id)
Set the specified tag to the specified value in the RG header with the specified id,...
Definition: SamFileHeader.cpp:311
SamFileHeader::removeHD
bool removeHD()
Remove the HD record.
Definition: SamFileHeader.cpp:554
SamFileHeader::addComment
bool addComment(const char *comment)
Add the specified comment to the header (do not include "@CO" or "\n").
Definition: SamFileHeader.cpp:213