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 
SamHeaderPG * getPG(const char *id)
Get the PG object with the specified id, returning NULL if there is no PG object with that key...
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 ReadHeader(SamFileHeader &header)
Reads the header section from the file and stores it in the passed in header.
Definition: SamFile.cpp:437
const char * getTagSO()
DEPRECATED.
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...
void reset()
Reset this header record to an empty state with no tags.
Sequence Dictionary.
const char * getNextComment()
Returns the comment on the next comment line.
bool isActiveHeaderRecord()
This record is active (true) if there is at least one tag set.
SamHeaderSQ * getSQ(const char *name)
Get the SQ object with the specified sequence name, returning NULL if there is no SQ object with that...
const char * getTagValue(const char *tag) const
Return the value associated with the specified tag.
const char * getHDTagValue(const char *tag)
Returns the value associated with the specified HD tag, returning "" if the tag does not exist in the...
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...
bool copy(const SamFileHeader &header)
Copy method copies the passed in header into this header.
bool addSQ(SamHeaderSQ *sq)
Add the SQ record to the header.
Child class of SamFile for reading files.
Definition: SamFile.h:455
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
void resetHeaderRecordIter()
Reset to the beginning of the header records so the next call to getNextHeaderRecord returns the firs...
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, remove the tag by specifying value="".
bool addKey(const char *value)
Add the key tag with the specified value (not for HD headers).
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=""...
bool removeHD()
Remove the HD record.
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, remove the tag by specifying value="".
SamHeaderHD * getHD()
Get the HD object, returning NULL if there is no HD record.
bool getHeaderString(std::string &header) const
Set the passed in string to the entire header string, clearing its current contents.
const char * getTypeString()
Return the type of this header record (HD, SQ, RG, or PG) as a string.
Allows the user to easily read/write a SAM/BAM file.
Definition: SamFile.h:35
bool removeRG(const char *id)
Remove RG record with the specified key.
SamHeaderRecord * getNextPGRecord()
Get the next PG header record.
SamStatus::Status GetStatus()
Get the Status of the last call that sets status.
Definition: SamFile.h:207
void resetHeader()
Initialize the header.
bool removeSQ(const char *name)
Remove SQ record with the specified key.
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...
bool WriteHeader(SamFileHeader &header)
Writes the specified header into the file.
Definition: SamFile.cpp:467
void resetPGRecordIter()
Reset to the beginning of the header records so the next call to getNextPGRecord returns the first PG...
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, remove the tag by specifying value="".
bool addRG(SamHeaderRG *rg)
Add the RG record to the header.
bool addComment(const char *comment)
Add the specified comment to the header (do not include "@CO" or "\n").
SamHeaderRecordType getType()
Return the type of this header record (HD, SQ, RG, or PG) as an enum.
bool getNextHeaderLine(std::string &headerLine)
Set the passed in string to the next header line, overwritting the passed in string.
This class allows a user to get/set the fields in a SAM/BAM Header.
Definition: SamFileHeader.h:34
void resetCommentIter()
Resets to the beginning of the comments so getNextComment returns the first comment.
SamHeaderRecord * getNextRGRecord()
Get the next RG header record.
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...
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 ReadRecord(SamFileHeader &header, SamRecord &record)
Reads the next record from the file & stores it in the passed in record.
Definition: SamFile.cpp:501
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 removePG(const char *id)
Remove PG record with the specified key.
Class providing an easy to use interface to get/set/operate on the fields in a SAM/BAM record...
Definition: SamRecord.h:51
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
void resetSQRecordIter()
Reset to the beginning of the header records so the next call to getNextSQRecord returns the first SQ...
bool addPG(SamHeaderPG *pg)
Add the PG record to the header.
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...
This class encapsulates the tag value pairs contained with a SAM Header line with accessors for getti...
void resetRGRecordIter()
Reset to the beginning of the header records so the next call to getNextRGRecord returns the first RG...
SamHeaderRecord * getNextSQRecord()
Get the next SQ header record.