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 // Remove this test since SM is no longer required, the RG would be added
472 // assert(samHeader.setRGTag("ID", "rgID", "rgID") == true);
473 // assert(samHeader.getHeaderString(headerString) == true);
474 // // New RG does not show up since it is still missing a required field.
475 // assert(headerString ==
476 // "@HD\tSO:queryname\tVN:3.1\n@PG\tID:newID\n@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n");
477 // assert(strcmp(samHeader.getRGTagValue("ID", "rgID"), "rgID") == 0);
478 
479  // Add the missing SM field.
480  assert(samHeader.setRGTag("SM", "sm1", "rgID") == true);
481  assert(samHeader.getHeaderString(headerString) == true);
482  assert(headerString ==
483  "@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");
484  assert(strcmp(samHeader.getRGTagValue("ID", "rgID"), "rgID") == 0);
485 
486  // Verify can't modify the key.
487  assert(samHeader.setRGTag("ID", "rgID1", "rgID") == false);
488  assert(samHeader.getHeaderString(headerString) == true);
489  assert(headerString ==
490  "@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");
491  assert(strcmp(samHeader.getRGTagValue("ID", "rgID"), "rgID") == 0);
492 
493  // Verify that the copied header did not change.
494  assert(newHeader.getHeaderString(headerString) == true);
495  assert(headerString == "@HD\tVN:1.0\n@SQ\tLN:123\tSN:chr20\n");
496  // Verify it was added to the parsed header.
497  assert(strcmp(newHeader.getSQTagValue("LN", "chr20"), "123") == 0);
498 
499  // Add a new RG Tag
500  assert(samHeader.setRGTag("SM", "sample1", "rgID1") == true);
501  assert(samHeader.getHeaderString(headerString) == true);
502  // String does not show the tag until all required fields are there.
503  assert(headerString ==
504  "@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");
505  assert(strcmp(samHeader.getRGTagValue("ID", "rgID1"), "rgID1") == 0);
506  assert(strcmp(samHeader.getRGTagValue("SM", "rgID1"), "sample1") == 0);
507 
508  // Modify an RG tag.
509  assert(samHeader.setRGTag("SM", "sample", "rgID1") == true);
510  assert(samHeader.getHeaderString(headerString) == true);
511  assert(headerString ==
512  "@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");
513  assert(strcmp(samHeader.getRGTagValue("ID", "rgID1"), "rgID1") == 0);
514  assert(strcmp(samHeader.getRGTagValue("SM", "rgID1"), "sample") == 0);
515 
516  // Test removing an rg that does not exist.
517  assert(samHeader.removeRG("rgID2") == true);
518  assert(samHeader.getHeaderString(headerString) == true);
519  assert(headerString ==
520  "@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");
521 
522  // Create a new RG, set some values and add it.
523  SamHeaderRG* rg = new SamHeaderRG();
524  // Try adding it without a key.
525  assert(samHeader.addRG(rg) == false);
526  assert(samHeader.getHeaderString(headerString) == true);
527  assert(headerString ==
528  "@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");
529  // Set some values in rg.
530  assert(rg->setTag("ID", "rgID2") == true);
531  assert(rg->setTag("SM", "sm2") == true);
532  assert(samHeader.getHeaderString(headerString) == true);
533  assert(headerString ==
534  "@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");
535  // Add the new RG.
536  assert(samHeader.addRG(rg) == true);
537  assert(samHeader.getHeaderString(headerString) == true);
538  assert(headerString ==
539  "@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");
540  assert(strcmp(samHeader.getRGTagValue("ID", "rgID2"), "rgID2") == 0);
541 
542  // Test trying to add another one with the same key.
543  rg = new SamHeaderRG();
544  assert(rg->setTag("ID", "rgID2") == true);
545  assert(samHeader.addRG(rg) == false);
546  assert(samHeader.getHeaderString(headerString) == true);
547  assert(headerString ==
548  "@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");
549 
550 
551  // Test removing the rg again.
552  assert(samHeader.removeRG("rgID2") == true);
553  assert(samHeader.getHeaderString(headerString) == true);
554  assert(headerString ==
555  "@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");
556 
557  // Test getting an rg tag that doesn't exist
558  assert(strcmp(samHeader.getRGTagValue("DS", "rgID"), "") == 0);
559  assert(samHeader.getHeaderString(headerString) == true);
560  assert(headerString ==
561  "@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");
562 
563  // Test getting an rg tag from a removed key
564  assert(strcmp(samHeader.getRGTagValue("ID", "rgID2"), "") == 0);
565  assert(samHeader.getHeaderString(headerString) == true);
566  assert(headerString ==
567  "@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");
568 
569  // Test getting an rg tag from an key that doesn't exist
570  assert(strcmp(samHeader.getRGTagValue("ID", "rgID22"), "") == 0);
571  assert(samHeader.getHeaderString(headerString) == true);
572  assert(headerString ==
573  "@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");
574 
575  // Test adding a null header.
576  rg = NULL;
577  assert(samHeader.addRG(rg) == false);
578  assert(samHeader.getHeaderString(headerString) == true);
579  assert(headerString ==
580  "@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");
581 
582  // Test adding the deleted header back in.
583  rg = new SamHeaderRG();
584  assert(rg->setTag("ID", "rgID2") == true);
585  assert(rg->setTag("SM", "sm2") == true);
586  assert(samHeader.addRG(rg) == true);
587  assert(samHeader.getHeaderString(headerString) == true);
588  assert(headerString ==
589  "@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");
590 
591  // Test adding an RG that is already there.
592  assert(samHeader.addHeaderLine("@RG\tID:rgID\tSM:sm5") == false);
593  assert(samHeader.getHeaderString(headerString) == true);
594  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");
595  // Verify it was added to the parsed header.
596  assert(strcmp(samHeader.getRGTagValue("SM", "rgID"), "sm1") == 0);
597 
598 
599  // Get an RG record then modify it.
600  rg = samHeader.getRG("rgID1");
601  assert(rg != NULL);
602  assert(rg->setTag("SM", "sample1") == true);
603  assert(samHeader.getHeaderString(headerString) == true);
604  assert(headerString ==
605  "@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");
606 
607  // Try to modify the key.
608  assert(rg->setTag("ID", "rgID111") == false);
609  assert(samHeader.getHeaderString(headerString) == true);
610  assert(headerString ==
611  "@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");
612 
613  ////////////////////////////////////////////////////////////////////////////
614  // Test getting a comment when there aren't any.
615  assert(strcmp(samHeader.getNextComment(), "") == 0);
616  assert(samHeader.getHeaderString(headerString) == true);
617  assert(headerString ==
618  "@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");
619 
620  // Test getting each headerline when there are no comments.
621  const char* hdrlinechar;
622  std::string hdrline;
623  assert(samHeader.getNextHeaderLine(hdrline));
624  hdrlinechar = hdrline.c_str();
625  // Test to make sure there is not memory corruption.
626  std::string tmpString = "@SQ\tSN:queryname\tVN:3.1\n";
627  assert(hdrline == "@HD\tSO:queryname\tVN:3.1\n");
628  assert(strcmp(hdrlinechar,
629  "@HD\tSO:queryname\tVN:3.1\n") == 0);
630 
631  assert(samHeader.getNextHeaderLine(hdrline));
632  assert(hdrline == "@PG\tID:newID\n");
633  assert(samHeader.getNextHeaderLine(hdrline));
634  assert(hdrline == "@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n");
635  assert(samHeader.getNextHeaderLine(hdrline));
636  assert(hdrline == "@RG\tID:rgID\tSM:sm1\n");
637  assert(samHeader.getNextHeaderLine(hdrline));
638  assert(hdrline == "@RG\tID:rgID1\tSM:sample1\n");
639  assert(samHeader.getNextHeaderLine(hdrline));
640  assert(hdrline == "@RG\tID:rgID2\tSM:sm2\n");
641  assert(!samHeader.getNextHeaderLine(hdrline));
642  assert(hdrline == "");
643  assert(!samHeader.getNextHeaderLine(hdrline));
644  assert(hdrline == "");
645  assert(samHeader.getHeaderString(headerString) == true);
646  assert(headerString ==
647  "@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");
648 
649  // Verify that getHeaderRecord returns nothing.
650  assert(samHeader.getNextHeaderRecord() == NULL);
651 
652  // Reset the header record iter.
653  samHeader.resetHeaderRecordIter();
654 
655  // Test getting each headerrecord when there are no comments.
656  SamHeaderRecord* hdrRec = samHeader.getNextHeaderRecord();
657  assert(hdrRec != NULL);
658  assert(strcmp(hdrRec->getTypeString(), "HD") == 0);
659  assert(hdrRec->getType() == SamHeaderRecord::HD);
660  assert(strcmp(hdrRec->getTagValue("SO"), "queryname") == 0);
661  assert(strcmp(hdrRec->getTagValue("VN"), "3.1") == 0);
662  hdrRec = samHeader.getNextHeaderRecord();
663  assert(hdrRec != NULL);
664  assert(strcmp(hdrRec->getTypeString(), "PG") == 0);
665  assert(hdrRec->getType() == SamHeaderRecord::PG);
666  assert(strcmp(hdrRec->getTagValue("ID"), "newID") == 0);
667  hdrRec = samHeader.getNextHeaderRecord();
668  assert(hdrRec != NULL);
669  assert(strcmp(hdrRec->getTypeString(), "SQ") == 0);
670  assert(hdrRec->getType() == SamHeaderRecord::SQ);
671  assert(strcmp(hdrRec->getTagValue("SN"), "newName") == 0);
672  assert(strcmp(hdrRec->getTagValue("AS"), "HG18") == 0);
673  assert(strcmp(hdrRec->getTagValue("LN"), "111") == 0);
674  hdrRec = samHeader.getNextHeaderRecord();
675  assert(hdrRec != NULL);
676  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
677  assert(hdrRec->getType() == SamHeaderRecord::RG);
678  assert(strcmp(hdrRec->getTagValue("ID"), "rgID") == 0);
679  assert(strcmp(hdrRec->getTagValue("SM"), "sm1") == 0);
680 
681  // Get the SQ Header Record (should have no affect on the general
682  // getNextHeaderRecord calls).
683  hdrRec = samHeader.getNextSQRecord();
684  assert(hdrRec != NULL);
685  assert(strcmp(hdrRec->getTypeString(), "SQ") == 0);
686  assert(hdrRec->getType() == SamHeaderRecord::SQ);
687  assert(strcmp(hdrRec->getTagValue("SN"), "newName") == 0);
688  assert(strcmp(hdrRec->getTagValue("AS"), "HG18") == 0);
689  assert(strcmp(hdrRec->getTagValue("LN"), "111") == 0);
690  // Only one SQ Header Record.
691  hdrRec = samHeader.getNextSQRecord();
692  assert(hdrRec == NULL);
693 
694  // Get the RG/PG Header Records (should have no affect on the general
695  // getNextHeaderRecord calls).
696  hdrRec = samHeader.getNextRGRecord();
697  assert(hdrRec != NULL);
698  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
699  assert(hdrRec->getType() == SamHeaderRecord::RG);
700  assert(strcmp(hdrRec->getTagValue("ID"), "rgID") == 0);
701  assert(strcmp(hdrRec->getTagValue("SM"), "sm1") == 0);
702  // Get the next RG record.
703  hdrRec = samHeader.getNextRGRecord();
704  assert(hdrRec != NULL);
705  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
706  assert(hdrRec->getType() == SamHeaderRecord::RG);
707  assert(strcmp(hdrRec->getTagValue("ID"), "rgID1") == 0);
708  assert(strcmp(hdrRec->getTagValue("SM"), "sample1") == 0);
709  // Get the PG record.
710  hdrRec = samHeader.getNextPGRecord();
711  assert(hdrRec != NULL);
712  assert(strcmp(hdrRec->getTypeString(), "PG") == 0);
713  assert(hdrRec->getType() == SamHeaderRecord::PG);
714  assert(strcmp(hdrRec->getTagValue("ID"), "newID") == 0);
715  // Get the last RG record.
716  hdrRec = samHeader.getNextRGRecord();
717  assert(hdrRec != NULL);
718  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
719  assert(hdrRec->getType() == SamHeaderRecord::RG);
720  assert(strcmp(hdrRec->getTagValue("ID"), "rgID2") == 0);
721  assert(strcmp(hdrRec->getTagValue("SM"), "sm2") == 0);
722  // Already got all RG Records.
723  hdrRec = samHeader.getNextRGRecord();
724  assert(hdrRec == NULL);
725  // Reset the RG record.
726  samHeader.resetRGRecordIter();
727  // Get the RG record.
728  hdrRec = samHeader.getNextRGRecord();
729  assert(hdrRec != NULL);
730  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
731  assert(hdrRec->getType() == SamHeaderRecord::RG);
732  assert(strcmp(hdrRec->getTagValue("ID"), "rgID") == 0);
733  assert(strcmp(hdrRec->getTagValue("SM"), "sm1") == 0);
734  // No more PG records.
735  hdrRec = samHeader.getNextPGRecord();
736  assert(hdrRec == NULL);
737  // No more SQ records.
738  hdrRec = samHeader.getNextSQRecord();
739  assert(hdrRec == NULL);
740  // Reset the SQ record iterator.
741  samHeader.resetSQRecordIter();
742  // No more PG records.
743  hdrRec = samHeader.getNextPGRecord();
744  assert(hdrRec == NULL);
745  // Get the now reset SQ record.
746  hdrRec = samHeader.getNextSQRecord();
747  assert(hdrRec != NULL);
748  assert(strcmp(hdrRec->getTypeString(), "SQ") == 0);
749  assert(hdrRec->getType() == SamHeaderRecord::SQ);
750  assert(strcmp(hdrRec->getTagValue("SN"), "newName") == 0);
751  assert(strcmp(hdrRec->getTagValue("AS"), "HG18") == 0);
752  assert(strcmp(hdrRec->getTagValue("LN"), "111") == 0);
753  // Only one SQ Header Record.
754  hdrRec = samHeader.getNextSQRecord();
755  assert(hdrRec == NULL);
756  // Reset the PG record iterator.
757  samHeader.resetPGRecordIter();
758  // No more SQ records.
759  hdrRec = samHeader.getNextSQRecord();
760  assert(hdrRec == NULL);
761  // Get the next RG record.
762  hdrRec = samHeader.getNextRGRecord();
763  assert(hdrRec != NULL);
764  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
765  assert(hdrRec->getType() == SamHeaderRecord::RG);
766  assert(strcmp(hdrRec->getTagValue("ID"), "rgID1") == 0);
767  assert(strcmp(hdrRec->getTagValue("SM"), "sample1") == 0);
768  // Get the PG record.
769  hdrRec = samHeader.getNextPGRecord();
770  assert(hdrRec != NULL);
771  assert(strcmp(hdrRec->getTypeString(), "PG") == 0);
772  assert(hdrRec->getType() == SamHeaderRecord::PG);
773  assert(strcmp(hdrRec->getTagValue("ID"), "newID") == 0);
774 
775 
776  hdrRec = samHeader.getNextHeaderRecord();
777  assert(hdrRec != NULL);
778  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
779  assert(hdrRec->getType() == SamHeaderRecord::RG);
780  assert(strcmp(hdrRec->getTagValue("ID"), "rgID1") == 0);
781  assert(strcmp(hdrRec->getTagValue("SM"), "sample1") == 0);
782  hdrRec = samHeader.getNextHeaderRecord();
783  assert(hdrRec != NULL);
784  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
785  assert(hdrRec->getType() == SamHeaderRecord::RG);
786  assert(strcmp(hdrRec->getTagValue("ID"), "rgID2") == 0);
787  assert(strcmp(hdrRec->getTagValue("SM"), "sm2") == 0);
788  hdrRec = samHeader.getNextHeaderRecord();
789  assert(hdrRec == NULL);
790  hdrRec = samHeader.getNextHeaderRecord();
791  assert(hdrRec == NULL);
792  assert(!samHeader.getNextHeaderLine(hdrline));
793  assert(hdrline == "");
794  assert(!samHeader.getNextHeaderLine(hdrline));
795  assert(hdrline == "");
796 
797  assert(samHeader.getHeaderString(headerString) == true);
798  assert(headerString ==
799  "@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");
800 
801  // Add some comments.
802  assert(samHeader.addComment("My Comment") == true);
803  assert(samHeader.getHeaderString(headerString) == true);
804  assert(headerString ==
805  "@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");
806 
807  // Call getNextHeaderRecord - still nothing.
808  hdrRec = samHeader.getNextHeaderRecord();
809  assert(hdrRec == NULL);
810 
811  // Call getNextHeaderLine - should return the comment.
812  assert(samHeader.getNextHeaderLine(hdrline));
813  assert(hdrline == "@CO\tMy Comment\n");
814  assert(!samHeader.getNextHeaderLine(hdrline));
815  assert(hdrline == "");
816  assert(!samHeader.getNextHeaderLine(hdrline));
817  assert(hdrline == "");
818 
819  // Call getNextCommentLine - should return the comment.
820  assert(strcmp(samHeader.getNextComment(), "My Comment") == 0);
821  assert(strcmp(samHeader.getNextComment(), "") == 0);
822  assert(strcmp(samHeader.getNextComment(), "") == 0);
823 
824  // Add another comment.
825  assert(samHeader.addComment("My Comment2") == true);
826  assert(samHeader.getHeaderString(headerString) == true);
827  assert(headerString ==
828  "@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");
829 
830  newHeader = samHeader;
831  assert(newHeader.getHeaderString(headerString) == true);
832  assert(headerString ==
833  "@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");
834 
835  // Call getNextHeaderLine - should return the comment.
836  assert(samHeader.getNextHeaderLine(hdrline));
837  assert(hdrline == "@CO\tMy Comment2\n");
838  assert(!samHeader.getNextHeaderLine(hdrline));
839  assert(hdrline == "");
840  assert(!samHeader.getNextHeaderLine(hdrline));
841  assert(hdrline == "");
842 
843  // Call getNextCommentLine - should return the comment.
844  assert(strcmp(samHeader.getNextComment(), "My Comment2") == 0);
845  assert(strcmp(samHeader.getNextComment(), "") == 0);
846  assert(strcmp(samHeader.getNextComment(), "") == 0);
847 
848  // Reset the header record iter.
849  samHeader.resetHeaderRecordIter();
850 
851  // Recall getNextCommentLine - should not return anything.
852  assert(strcmp(samHeader.getNextComment(), "") == 0);
853  assert(strcmp(samHeader.getNextComment(), "") == 0);
854 
855  // Reset the next comment iter.
856  samHeader.resetCommentIter();
857 
858  // Call the get next headerLine, record, comment interspersed with
859  // each other.
860  hdrRec = samHeader.getNextHeaderRecord();
861  assert(hdrRec != NULL);
862  assert(strcmp(hdrRec->getTypeString(), "HD") == 0);
863  assert(hdrRec->getType() == SamHeaderRecord::HD);
864  assert(strcmp(hdrRec->getTagValue("SO"), "queryname") == 0);
865  assert(strcmp(hdrRec->getTagValue("VN"), "3.1") == 0);
866  assert(samHeader.getNextHeaderLine(hdrline));
867  assert(hdrline == "@PG\tID:newID\n");
868  assert(samHeader.getNextHeaderLine(hdrline));
869  assert(hdrline == "@SQ\tSN:newName\tLN:111\tAS:HG18\tSP:species\n");
870  hdrRec = samHeader.getNextHeaderRecord();
871  assert(hdrRec != NULL);
872  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
873  assert(hdrRec->getType() == SamHeaderRecord::RG);
874  assert(strcmp(hdrRec->getTagValue("ID"), "rgID") == 0);
875  hdrRec = samHeader.getNextHeaderRecord();
876  assert(hdrRec != NULL);
877  assert(strcmp(samHeader.getNextComment(), "My Comment") == 0);
878  assert(strcmp(hdrRec->getTypeString(), "RG") == 0);
879  assert(hdrRec->getType() == SamHeaderRecord::RG);
880  assert(strcmp(hdrRec->getTagValue("ID"), "rgID1") == 0);
881  assert(strcmp(hdrRec->getTagValue("SM"), "sample1") == 0);
882  assert(samHeader.getNextHeaderLine(hdrline));
883  assert(hdrline == "@RG\tID:rgID2\tSM:sm2\n");
884  hdrRec = samHeader.getNextHeaderRecord();
885  assert(hdrRec == NULL);
886  assert(samHeader.getNextHeaderLine(hdrline));
887  assert(hdrline == "@CO\tMy Comment\n");
888  hdrRec = samHeader.getNextHeaderRecord();
889  assert(hdrRec == NULL);
890  assert(samHeader.getNextHeaderLine(hdrline));
891  assert(hdrline == "@CO\tMy Comment2\n");
892  assert(!samHeader.getNextHeaderLine(hdrline));
893  assert(hdrline == "");
894  assert(strcmp(samHeader.getNextComment(), "My Comment2") == 0);
895  assert(!samHeader.getNextHeaderLine(hdrline));
896  assert(hdrline == "");
897  hdrRec = samHeader.getNextHeaderRecord();
898  assert(hdrRec == NULL);
899  assert(strcmp(samHeader.getNextComment(), "") == 0);
900  assert(strcmp(samHeader.getNextComment(), "") == 0);
901 
902  samOut.WriteHeader(samHeader);
903 
904  // Reset the header.
905  samHeader.resetHeader();
906  assert(samHeader.getHeaderString(headerString) == true);
907  assert(headerString == "");
908  assert(!samHeader.getNextHeaderLine(hdrline));
909  assert(hdrline == "");
910  assert(strcmp(samHeader.getHDTagValue("SO"), "") == 0);
911  assert(strcmp(samHeader.getHDTagValue("VN"), "") == 0);
912 
913  // Try adding a key to the HD tag.
914  hd = new SamHeaderHD();
915  assert(hd->addKey("3.1") == false);
916  assert(strcmp(hd->getTagValue("VN"), "") == 0);
917  assert(hd->isActiveHeaderRecord() == false);
918 
919  assert(hd->setTag("VN", "3.1") == true);
920  assert(hd->isActiveHeaderRecord() == true);
921  assert(strcmp(hd->getTagValue("VN"), "3.1") == 0);
922 
923  // Verify the copied header did not change.
924  assert(newHeader.getHeaderString(headerString) == true);
925  assert(headerString ==
926  "@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");
927  // Verify it was added to the parsed header.
928  assert(strcmp(newHeader.getSQTagValue("LN", "chr20"), "") == 0);
929 }
930 
931 
932 void testWriteCopiedHeader(const char* fileName)
933 {
934  SamFile samIn;
935  assert(samIn.OpenForRead(fileName));
936 
937  SamFile samOut;
938  assert(samOut.OpenForWrite("results/MyTestOut2.bam"));
939  SamFile samOut2;
940  assert(samOut2.OpenForWrite("results/MyTestOut2.sam"));
941 
942  // Read the sam header.
943  SamFileHeader samHeader;
944  assert(samIn.ReadHeader(samHeader));
945  validateHeader(samHeader);
946 
947  SamFileHeader newHeader;
948 
949  std::string hdrLine;
950  assert(samHeader.getNextHeaderLine(hdrLine));
951  newHeader.addHeaderLine("@HD\tVN:1.02");
952  bool hdrStatus = true;
953  while(hdrStatus)
954  {
955  newHeader.addHeaderLine(hdrLine.c_str());
956  hdrStatus = samHeader.getNextHeaderLine(hdrLine);
957  }
958 
959  // Write the sam header.
960  assert(samOut.WriteHeader(newHeader));
961  assert(samOut2.WriteHeader(newHeader));
962 
963  SamRecord samRecord;
964 
965  // Keep reading records until ReadRecord returns false.
966  while(samIn.ReadRecord(samHeader, samRecord))
967  {
968  // Successfully read a record from the file, so write it.
969  assert(samOut.WriteRecord(newHeader, samRecord));
970  assert(samOut2.WriteRecord(newHeader, samRecord));
971  }
972 
973  assert(samIn.GetStatus() == SamStatus::NO_MORE_RECS);
974 
975  // Close the output files.
976  samOut.Close();
977  samOut2.Close();
978 
979  SamFileReader bamRead("results/MyTestOut2.bam");
980  SamFileReader samRead("results/MyTestOut2.sam");
981 
982  // Read and check the header.
983  assert(samRead.ReadHeader(samHeader));
984  validateHeaderFields(samHeader);
985  std::string headerString = "";
986  assert(samHeader.getHeaderString(headerString) == true);
987  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");
988 
989  assert(bamRead.ReadHeader(samHeader));
990  validateHeaderFields(samHeader);
991  headerString = "";
992  assert(samHeader.getHeaderString(headerString) == true);
993  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");
994 
995  assert(samHeader.getNextHeaderLine(hdrLine));
996  std::string expectedString = "@HD\tVN:1.02\n";
997 
998  assert(expectedString == hdrLine);
999 
1000 
1001  // TODO - validate reading these written records back in.
1002 
1003 }
1004 
This class allows a user to get/set the fields in a SAM/BAM Header.
Definition: SamFileHeader.h:35
SamHeaderPG * getPG(const char *id)
Get the PG object with the specified id, returning NULL if there is no PG object with that key.
bool addPG(SamHeaderPG *pg)
Add the PG record to the header.
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,...
SamHeaderSQ * getSQ(const char *name)
Get the SQ object with the specified sequence name, returning NULL if there is no SQ object with that...
SamHeaderHD * getHD()
Get the HD object, returning NULL if there is no HD record.
void resetRGRecordIter()
Reset to the beginning of the header records so the next call to getNextRGRecord returns the first RG...
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,...
const char * getHDTagValue(const char *tag)
Returns the value associated with the specified HD tag, returning "" if the tag does not exist in the...
bool addRG(SamHeaderRG *rg)
Add the RG record to the header.
bool getNextHeaderLine(std::string &headerLine)
Set the passed in string to the next header line, overwritting the passed in string.
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...
SamHeaderRecord * getNextPGRecord()
Get the next PG header record.
bool removePG(const char *id)
Remove PG record with the specified key.
bool addSQ(SamHeaderSQ *sq)
Add the SQ record to the header.
bool removeRG(const char *id)
Remove RG record with the specified key.
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,...
bool addComment(const char *comment)
Add the specified comment to the header (do not include "@CO" or "\n").
const char * getTagSO()
DEPRECATED.
const char * getNextComment()
Returns the comment on the next comment line.
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...
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.
bool removeHD()
Remove the HD record.
void resetSQRecordIter()
Reset to the beginning of the header records so the next call to getNextSQRecord returns the first SQ...
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,...
bool getHeaderString(std::string &header) const
Set the passed in string to the entire header string, clearing its current contents.
bool copy(const SamFileHeader &header)
Copy method copies the passed in header into this header.
void resetHeaderRecordIter()
Reset to the beginning of the header records so the next call to getNextHeaderRecord returns the firs...
SamHeaderRecord * getNextRGRecord()
Get the next RG header record.
SamHeaderRecord * getNextSQRecord()
Get the next SQ header record.
void resetHeader()
Initialize the header.
bool removeSQ(const char *name)
Remove SQ record with the specified key.
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,...
void resetPGRecordIter()
Reset to the beginning of the header records so the next call to getNextPGRecord returns the first PG...
SamHeaderRG * getRG(const char *id)
Get the RG object with the specified read group identifier, returning NULL if there is no RG object w...
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="".
void resetCommentIter()
Resets to the beginning of the comments so getNextComment returns the first comment.
Child class of SamFile for reading files.
Definition: SamFile.h:461
Allows the user to easily read/write a SAM/BAM file.
Definition: SamFile.h:36
bool ReadHeader(SamFileHeader &header)
Reads the header section from the file and stores it in the passed in header.
Definition: SamFile.cpp:450
void Close()
Close the file if there is one open.
Definition: SamFile.cpp:400
bool ReadRecord(SamFileHeader &header, SamRecord &record)
Reads the next record from the file & stores it in the passed in record.
Definition: SamFile.cpp:514
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
SamStatus::Status GetStatus()
Get the Status of the last call that sets status.
Definition: SamFile.h:212
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
bool WriteHeader(SamFileHeader &header)
Writes the specified header into the file.
Definition: SamFile.cpp:480
bool WriteRecord(SamFileHeader &header, SamRecord &record)
Writes the specified record into the file.
Definition: SamFile.cpp:632
This class encapsulates the tag value pairs contained with a SAM Header line with accessors for getti...
const char * getTagValue(const char *tag) const
Return the value associated with the specified tag.
const char * getTypeString()
Return the type of this header record (HD, SQ, RG, or PG) as a string.
void reset()
Reset this header record to an empty state with no tags.
SamHeaderRecordType getType()
Return the type of this header record (HD, SQ, RG, or PG) as an enum.
bool isActiveHeaderRecord()
This record is active (true) if there is at least one tag set.
bool addKey(const char *value)
Add the key tag with the specified value (not for HD headers).
@ SQ
Sequence Dictionary.
@ RG
Read Group.
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.
Class providing an easy to use interface to get/set/operate on the fields in a SAM/BAM record.
Definition: SamRecord.h:52
@ 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