1 /* $Id: test_align.cpp 605072 2020-04-06 21:17:53Z vasilche $
2 * ===========================================================================
3 *
4 * PUBLIC DOMAIN NOTICE
5 * National Center for Biotechnology Information
6 *
7 * This software/database is a "United States Government Work" under the
8 * terms of the United States Copyright Act. It was written as part of
9 * the author's official duties as a United States Government employee and
10 * thus cannot be copyrighted. This software/database is freely available
11 * to the public for use. The National Library of Medicine and the U.S.
12 * Government have not placed any restriction on its use or reproduction.
13 *
14 * Although all reasonable efforts have been taken to ensure the accuracy
15 * and reliability of the software and data, the NLM and the U.S.
16 * Government do not and cannot warrant the performance or results that
17 * may be obtained by using this software or data. The NLM and the U.S.
18 * Government disclaim all warranties, express or implied, including
19 * warranties of performance, merchantability or fitness for any particular
20 * purpose.
21 *
22 * Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * Author: Andrey Yazhuk
27 *
28 * File Description:
29 *
30 * ===========================================================================
31 */
32
33 #include <ncbi_pch.hpp>
34
35 #include "test_align.hpp"
36
37 #include <util/align_range.hpp>
38 #include <util/align_range_coll.hpp>
39
40 #include <common/test_assert.h> /* This header must go last */
41
42
43 BEGIN_NCBI_SCOPE
44
45 typedef CAlignRange<TSignedSeqPos> TAlignRange;
46 typedef CAlignRangeCollectionList<TAlignRange> TAlignColl;
47 typedef CRange<TSignedSeqPos> TSignedRange;
48
49
50 ///////////////////////////////////////////////////////////////////////////////
51 /// TAlignRange - Helper functions
52
53 // checks that "r" satisfies design assumptions for CAlignRange
54 // evaluates internal invariants that must be true for any instnace of CAlignRange
AR_Test_Invariants(const TAlignRange & r)55 void AR_Test_Invariants(const TAlignRange& r)
56 {
57 // check from <= to_open
58 BOOST_CHECK(r.GetFirstFrom() <= r.GetFirstToOpen());
59 BOOST_CHECK(r.GetSecondFrom() <= r.GetSecondToOpen());
60
61 // check to + 1 == to_open
62 BOOST_CHECK_EQUAL(r.GetFirstTo() + 1, r.GetFirstToOpen());
63 BOOST_CHECK_EQUAL(r.GetSecondTo() + 1, r.GetSecondToOpen());
64
65 // check length
66 BOOST_CHECK_EQUAL(r.GetLength(), r.GetFirstToOpen() - r.GetFirstFrom());
67 BOOST_CHECK_EQUAL(r.GetLength(), r.GetSecondToOpen() - r.GetSecondFrom());
68
69 // check direction
70 BOOST_CHECK_EQUAL(r.IsDirect(), ! r.IsReversed());
71
72 if(r.Empty()) {
73 BOOST_CHECK(r.GetLength() <= 0);
74 } else {
75 BOOST_CHECK(r.GetLength() > 0);
76
77 // check mapping of the ends
78 // first -> second
79 TSignedSeqPos tr_from = r.GetSecondPosByFirstPos(r.GetFirstFrom());
80 TSignedSeqPos tr_to = r.GetSecondPosByFirstPos(r.GetFirstTo());
81 if(r.IsDirect()) {
82 BOOST_CHECK_EQUAL(tr_from, r.GetSecondFrom());
83 BOOST_CHECK_EQUAL(tr_to, r.GetSecondTo());
84 } else {
85 BOOST_CHECK_EQUAL(tr_from, r.GetSecondTo());
86 BOOST_CHECK_EQUAL(tr_to, r.GetSecondFrom());
87 }
88 // second -> first
89 tr_from = r.GetFirstPosBySecondPos(r.GetSecondFrom());
90 tr_to = r.GetFirstPosBySecondPos(r.GetSecondTo());
91 if(r.IsDirect()) {
92 BOOST_CHECK_EQUAL(tr_from, r.GetFirstFrom());
93 BOOST_CHECK_EQUAL(tr_to, r.GetFirstTo());
94 } else {
95 BOOST_CHECK_EQUAL(tr_from, r.GetFirstTo());
96 BOOST_CHECK_EQUAL(tr_to, r.GetFirstFrom());
97 }
98 }
99 }
100
101
102 // checks that "r" indeed represents the specified range
AR_Test_Identical(const TAlignRange & r,TSignedSeqPos from_1,TSignedSeqPos to_1,TSignedSeqPos from_2,TSignedSeqPos to_2,bool direct)103 void AR_Test_Identical(const TAlignRange& r, TSignedSeqPos from_1, TSignedSeqPos to_1,
104 TSignedSeqPos from_2, TSignedSeqPos to_2, bool direct)
105 {
106 // first check that the range is valid
107 AR_Test_Invariants(r);
108
109 // now check that the range does represent given values
110 BOOST_CHECK_EQUAL(r.GetFirstFrom(), from_1);
111 BOOST_CHECK_EQUAL(r.GetFirstTo(), to_1);
112 BOOST_CHECK_EQUAL(r.GetFirstToOpen(), to_1 + 1);
113
114 BOOST_CHECK_EQUAL(r.GetSecondFrom(), from_2);
115 BOOST_CHECK_EQUAL(r.GetSecondTo(), to_2);
116 BOOST_CHECK_EQUAL(r.GetSecondToOpen(), to_2 + 1);
117
118 BOOST_REQUIRE(to_1 - from_1 == to_2 - from_2); // test validity
119
120 BOOST_CHECK_EQUAL(r.GetLength(), to_1 - from_1 + 1);
121
122 BOOST_CHECK_EQUAL(r.IsDirect(), direct);
123 }
124
125
AR_Test_Direction(const TAlignRange & r,bool dir)126 void AR_Test_Direction(const TAlignRange& r, bool dir)
127 {
128 BOOST_CHECK_EQUAL(r.IsDirect(), dir);
129 BOOST_CHECK_EQUAL(r.IsReversed(), ! dir);
130 }
131
132
operator <<(ostream & out,const TAlignRange & r)133 ostream& operator<<(ostream& out, const TAlignRange& r)
134 {
135 return out << "TAlignRange [" << r.GetFirstFrom() << ", " << r.GetSecondFrom()
136 << ", " << r.GetLength() << "]";
137 }
138
139
140 ///////////////////////////////////////////////////////////////////////////////
141 /// Test Cases
142
143 BOOST_AUTO_TEST_SUITE(CAlignRange_Unit_Test)
144
BOOST_AUTO_TEST_CASE(AR_Test_SetGet)145 BOOST_AUTO_TEST_CASE(AR_Test_SetGet)
146 {
147 TAlignRange r;
148
149 // test position set/get
150 r.SetFirstFrom(1);
151 r.SetSecondFrom(5);
152 r.SetLength(20);
153 AR_Test_Identical(r, 1, 20, 5, 24, true);
154
155 r.SetFirstFrom(7);
156 r.SetSecondFrom(13);
157 r.SetLength(1);
158 AR_Test_Identical(r, 7, 7, 13, 13, true);
159
160 r.SetLength(0);
161 AR_Test_Identical(r, 7, 6, 13, 12, true);
162
163
164 // test direction set/get
165 r.SetDirect(true);
166 AR_Test_Direction(r, true);
167 r.SetDirect(false);
168 AR_Test_Direction(r, false);
169 r.SetDirect(); // test default
170 AR_Test_Direction(r, true);
171
172 r.SetReversed(true);
173 AR_Test_Direction(r, false);
174 r.SetReversed(false);
175 AR_Test_Direction(r, true);
176 r.SetReversed(); // test default
177 AR_Test_Direction(r, false);
178 }
179
180
BOOST_AUTO_TEST_CASE(AR_Test_Constructors)181 BOOST_AUTO_TEST_CASE(AR_Test_Constructors)
182 {
183 // check default constructor
184 {
185 TAlignRange r;
186 AR_Test_Identical(r, TAlignRange::GetPositionMax(), TAlignRange::GetPositionMax() - 1,
187 TAlignRange::GetPositionMax(), TAlignRange::GetPositionMax()-1, true);
188 }
189 {
190 TAlignRange r(7, 13, 100, true);
191 AR_Test_Identical(r, 7, 106, 13, 112, true);
192 }
193 {
194 TAlignRange r(1000, 1, 100000, false);
195 AR_Test_Identical(r, 1000, 100999, 1, 100000, false);
196
197 //TAlignRange r2 = r;
198 //AR_Test_Identical(r2, 1000, 100999, 1, 100000, false);
199 }
200 }
201
202
BOOST_AUTO_TEST_CASE(AR_Test_Equality)203 BOOST_AUTO_TEST_CASE(AR_Test_Equality)
204 {
205 {
206 TAlignRange r1, r2;
207 BOOST_CHECK(r1 == r2);
208 BOOST_CHECK( ! (r1 != r2));
209 }
210 {
211 TAlignRange r1(1, 13, 1000, false);
212 TAlignRange r2(1, 13, 1000, false);
213
214 BOOST_CHECK(r1 == r2);
215 BOOST_CHECK( ! (r1 != r2));
216
217 // change FirstFrom, check that not equal
218 TAlignRange r3(100000, 13, 1000, false);
219 BOOST_CHECK(r1 != r3);
220 BOOST_CHECK( ! (r1 == r3));
221
222 // change SecondFrom, check that not equal
223 TAlignRange r4(1, 100013, 1000, false);
224 BOOST_CHECK(r1 != r4);
225 BOOST_CHECK( ! (r1 == r4));
226
227 // change Length, check that not equal
228 TAlignRange r5(1, 13, 101000, false);
229 BOOST_CHECK(r1 != r5);
230 BOOST_CHECK( ! (r1 == r5));
231
232 // change direction, check that not equal
233 TAlignRange r6(1, 13, 1000, true);
234 BOOST_CHECK(r1 != r6);
235 BOOST_CHECK( ! (r1 == r6));
236 }
237 }
238
239
240 // check that both positions are transformed to invalid values
AR_Test_OutOfBounds_Transform(const TAlignRange & r,TSignedSeqPos pos_1,TSignedSeqPos pos_2)241 void AR_Test_OutOfBounds_Transform(const TAlignRange& r, TSignedSeqPos pos_1, TSignedSeqPos pos_2)
242 {
243 BOOST_CHECK_EQUAL(r.FirstContains(pos_1), false);
244 TSignedSeqPos pos = r.GetSecondPosByFirstPos(pos_1);
245 BOOST_CHECK_EQUAL(pos, -1);
246
247 BOOST_CHECK_EQUAL(r.SecondContains(pos_2), false);
248 pos = r.GetFirstPosBySecondPos(pos_2);
249 BOOST_CHECK_EQUAL(pos, -1);
250 }
251
252
BOOST_AUTO_TEST_CASE(AR_Test_CoordTransform)253 BOOST_AUTO_TEST_CASE(AR_Test_CoordTransform)
254 {
255 // AR_Test_Invariants() already checks that ends map to each other
256 // from <-> from or from <-> to
257
258 // seg [10, 59], [100, 149] direct
259 TAlignRange r(10, 100, 50, true);
260
261 // a point inside
262 TSignedSeqPos pos = r.GetSecondPosByFirstPos(20);
263 BOOST_CHECK_EQUAL(pos, 110);
264 pos = r.GetFirstPosBySecondPos(110);
265 BOOST_CHECK_EQUAL(pos, 20);
266
267 // check the edges
268 AR_Test_OutOfBounds_Transform(r, 9, 99);
269 AR_Test_OutOfBounds_Transform(r, 60, 150);
270
271 // check values far away
272 AR_Test_OutOfBounds_Transform(r, 0, 0);
273 AR_Test_OutOfBounds_Transform(r, 1000, 1000);
274
275 // seg [10, 59], [100, 149] reversed
276 r.SetReversed();
277
278 // a point inside
279 pos = r.GetSecondPosByFirstPos(20);
280 BOOST_CHECK_EQUAL(pos, 139);
281 pos = r.GetFirstPosBySecondPos(139);
282 BOOST_CHECK_EQUAL(pos, 20);
283
284 // check the edges
285 AR_Test_OutOfBounds_Transform(r, 9, 99);
286 AR_Test_OutOfBounds_Transform(r, 60, 150);
287
288 // check values far away
289 AR_Test_OutOfBounds_Transform(r, 0, 0);
290 AR_Test_OutOfBounds_Transform(r, 1000, 1000);
291 }
292
293
BOOST_AUTO_TEST_CASE(AR_Test_Empty)294 BOOST_AUTO_TEST_CASE(AR_Test_Empty)
295 {
296 TAlignRange r = TAlignRange::GetEmpty();
297 BOOST_CHECK(r.Empty());
298 BOOST_CHECK( !r.NotEmpty() );
299 BOOST_CHECK_EQUAL(r.GetFirstFrom(), TAlignRange::GetEmptyFrom());
300 BOOST_CHECK_EQUAL(r.GetFirstToOpen(), TAlignRange::GetEmptyToOpen());
301 BOOST_CHECK_EQUAL(r.GetFirstTo(), TAlignRange::GetEmptyTo());
302 BOOST_CHECK_EQUAL(r.GetSecondFrom(), TAlignRange::GetEmptyFrom());
303 BOOST_CHECK_EQUAL(r.GetSecondToOpen(), TAlignRange::GetEmptyToOpen());
304 BOOST_CHECK_EQUAL(r.GetSecondTo(), TAlignRange::GetEmptyTo());
305 BOOST_CHECK_EQUAL(r.GetLength(), TAlignRange::GetEmptyLength());
306 }
307
308
AR_Test_Clip(TSignedSeqPos clip_from,TSignedSeqPos clip_to,const TAlignRange & r,TSignedSeqPos res_from_1,TSignedSeqPos res_from_2,TSignedSeqPos res_len)309 void AR_Test_Clip(TSignedSeqPos clip_from, TSignedSeqPos clip_to, const TAlignRange& r,
310 TSignedSeqPos res_from_1, TSignedSeqPos res_from_2, TSignedSeqPos res_len)
311 {
312 typedef CRange<TSignedSeqPos> TRange;
313
314 TAlignRange r1(r);
315 TRange clip_1(clip_from, clip_to);
316
317 TAlignRange r2 = r1.IntersectionWith(clip_1);
318 r1.IntersectWith(clip_1);
319
320 TAlignRange res_1(res_from_1, res_from_2, res_len, r.IsDirect());
321 BOOST_CHECK_EQUAL(res_1, r1);
322 BOOST_CHECK_EQUAL(res_1, r2);
323 }
324
325
BOOST_AUTO_TEST_CASE(AR_Test_Intersect)326 BOOST_AUTO_TEST_CASE(AR_Test_Intersect)
327 {
328 {
329 // seg [1001, 1100], [2001, 2100] direct
330 TAlignRange r(1001, 2001, 100, true);
331
332 AR_Test_Clip(0, 1050, r, 1001, 2001, 50); // left overlapping
333 AR_Test_Clip(1081, 5000, r, 1081, 2081, 20); // right overlapping
334 AR_Test_Clip(1021, 1060, r, 1021, 2021, 40); // clip in the middle
335 AR_Test_Clip(0, 5000, r, 1001, 2001, 100); // clip the whole range - no changes
336 AR_Test_Clip(0, 10, r, 1001, 2001, 0); // no intersection - empty
337 AR_Test_Clip(1001, 2001, r, 1001, 2001, 100); // exact clip - no changes
338 }
339 {
340 // seg [1001, 1100], [2001, 2100] reversed
341 TAlignRange r(1001, 2001, 100, false);
342
343 AR_Test_Clip(0, 1050, r, 1001, 2051, 50); // left overlapping
344 AR_Test_Clip(1081, 5000, r, 1081, 2001, 20); // right overlapping
345 AR_Test_Clip(1021, 1060, r, 1021, 2041, 40); // clip in the middle
346 AR_Test_Clip(0, 5000, r, 1001, 2001, 100); // clip the whole range - no changes
347 AR_Test_Clip(0, 10, r, 1001, 2101, 0); // no intersection - empty
348 AR_Test_Clip(1001, 2001, r, 1001, 2001, 100); // exact clip - no changes
349 }
350 }
351
352
AR_Test_Combine_Abutting(const TAlignRange & r,const TAlignRange & r_a,const TAlignRange & r_res)353 void AR_Test_Combine_Abutting(const TAlignRange& r, const TAlignRange& r_a, const TAlignRange& r_res)
354 {
355 BOOST_REQUIRE(r.IsAbutting(r_a)); // precondition
356 BOOST_REQUIRE(r_a.IsAbutting(r));
357
358 TAlignRange r_1(r);
359 r_1.CombineWithAbutting(r_a);
360 TAlignRange r_2 = r.CombinationWithAbutting(r_a);
361
362 // check that the operation is symmetrical
363 TAlignRange r_3(r_a);
364 r_3.CombineWithAbutting(r);
365 TAlignRange r_4 = r_a.CombinationWithAbutting(r);
366
367 BOOST_CHECK_EQUAL(r_res, r_1);
368 BOOST_CHECK_EQUAL(r_res, r_2);
369 BOOST_CHECK_EQUAL(r_res, r_3);
370 BOOST_CHECK_EQUAL(r_res, r_4);
371 }
372
373 /// check CAlignRange::IsAbutting(), CombineWithAbutting() and
374 /// CombinationWithAbutting() functions
BOOST_AUTO_TEST_CASE(AR_Test_Combine)375 BOOST_AUTO_TEST_CASE(AR_Test_Combine)
376 {
377 {
378 // seg [1001, 1100], [2001, 2100] direct
379 TAlignRange r(1001, 2001, 100, true);
380
381 TAlignRange r_1(0, 0, 10, true); // r_1 is far away from r
382 BOOST_CHECK_EQUAL(r.IsAbutting(r_1), false);
383 BOOST_CHECK_EQUAL(r_1.IsAbutting(r), false);
384
385 TAlignRange r_2(1050, 2050, 10, true); // r_2 is inside r
386 BOOST_CHECK_EQUAL(r.IsAbutting(r_2), false);
387 BOOST_CHECK_EQUAL(r_2.IsAbutting(r), false);
388
389 TAlignRange r_3(1101, 2101, 50, false); // close but reversed
390 BOOST_CHECK_EQUAL(r.IsAbutting(r_3), false);
391 BOOST_CHECK_EQUAL(r_3.IsAbutting(r), false);
392 }
393 // combine direct ranges
394 {
395 // seg [1001, 1100], [2001, 2100] direct
396 TAlignRange r(1001, 2001, 100, true);
397
398 // [1101, 1150], [2101, 2150] direct
399 TAlignRange r_a_1(1101, 2101, 50, true);
400 TAlignRange res_1(1001, 2001, 150, true);
401 AR_Test_Combine_Abutting(r, r_a_1, res_1);
402
403 // empty adjacent ranges
404 TAlignRange r_a_2(1001, 2001, 0, true);
405 AR_Test_Combine_Abutting(r, r_a_2, r);
406
407 TAlignRange r_a_3(1101, 2101, 0, true);
408 AR_Test_Combine_Abutting(r, r_a_3, r);
409 }
410 // combine reversed ranges
411 {
412 // seg [1001, 1100], [2001, 2100] reversed
413 TAlignRange r(1001, 2001, 100, false);
414
415 // [1101, 1150], [1951, 2000] reversed
416 TAlignRange r_a_1(1101, 1951, 50, false);
417 TAlignRange res_1(1001, 1951, 150, false);
418 AR_Test_Combine_Abutting(r, r_a_1, res_1);
419
420 // empty adjacent ranges
421 TAlignRange r_a_2(1001, 2101, 0, false);
422 AR_Test_Combine_Abutting(r, r_a_2, r);
423
424 TAlignRange r_a_3(1101, 2001, 0, false);
425 AR_Test_Combine_Abutting(r, r_a_3, r);
426 }
427 // combine empty ranges
428 {
429 // empty seg [1001, 1000], [2001, 2000] direct
430 TAlignRange r_1(1001, 2001, 0, true);
431 AR_Test_Combine_Abutting(r_1, r_1, r_1);
432
433 // empty seg [1001, 1000], [2001, 2000] reversed
434 TAlignRange r_2(1001, 2001, 0, false);
435 AR_Test_Combine_Abutting(r_2, r_2, r_2);
436 }
437 }
438
439 BOOST_AUTO_TEST_SUITE_END()
440
441
442 ///////////////////////////////////////////////////////////////////////////////
443 /// TAlignColl - Helper functions
444
445 struct SARange {
446 TSignedSeqPos m_FirstFrom;
447 TSignedSeqPos m_SecondFrom;
448 TSignedSeqPos m_Length;
449 bool m_Direct;
450
operator ==SARange451 bool operator==(const TAlignRange& r) const
452 {
453 return m_FirstFrom == r.GetFirstFrom() && m_SecondFrom == r.GetSecondFrom() &&
454 m_Length == r.GetLength() && m_Direct == r.IsDirect();
455 }
operator !=SARange456 bool operator!=(const TAlignRange& r) const
457 {
458 return !operator==(r);
459 }
460 };
461 typedef vector<SARange> SARanges;
462
operator <<(ostream & out,const SARange & r)463 ostream& operator<<(ostream& out, const SARange& r)
464 {
465 return out << "[ " << r.m_FirstFrom << ", " << r.m_SecondFrom
466 << ", " << r.m_Length << ", " << (r.m_Direct?"true":"false") << "]";
467 }
468
operator <<(ostream & out,const SARanges & rr)469 ostream& operator<<(ostream& out, const SARanges& rr)
470 {
471 out << "{";
472 for ( size_t i = 0; i < rr.size(); ++i ) {
473 if ( i ) out << ',';
474 out << ' ' << rr[i];
475 }
476 return out << " }";
477 }
478
479
AC_AddToCollection(TAlignColl & coll,const SARange * ranges,size_t count)480 void AC_AddToCollection(TAlignColl& coll, const SARange* ranges, size_t count)
481 {
482 for (size_t i = 0; i < count; ++i) {
483 const SARange& st = ranges[i];
484 TAlignRange r(st.m_FirstFrom, st.m_SecondFrom, st.m_Length, st.m_Direct);
485 coll.insert(r);
486 }
487 }
488
AC_Collection_Equals(TAlignColl & coll,const SARange * ranges,size_t count)489 void AC_Collection_Equals(TAlignColl& coll, const SARange* ranges, size_t count)
490 {
491 TAlignColl::const_iterator it = coll.begin();
492 BOOST_REQUIRE(count == coll.size());
493
494 for (size_t i = 0; i < count; ++i, ++it) {
495 const SARange& st = ranges[i];
496 const TAlignRange& r = *it;
497 BOOST_CHECK_EQUAL(st, r);
498 }
499 }
500
operator <<(ostream & out,const TAlignColl & coll)501 ostream& operator<<(ostream& out, const TAlignColl& coll)
502 {
503 char s[32];
504 sprintf(s, "%X", (unsigned int) coll.GetFlags());
505 out << "CAlignRangeCollection Flags = " << s << ", : ";
506
507 for (TAlignColl::const_iterator it = coll.begin(); it != coll.end(); ++it) {
508 const TAlignRange& r = *it;
509 out << "[" << r.GetFirstFrom() << ", " << r.GetSecondFrom() << ", "
510 << r.GetLength() << ", " << (r.IsDirect() ? "true" : "false") << "]";
511 }
512 return out;
513 }
514
operator <<(ostream & out,const TSignedRange & r)515 ostream& operator<<(ostream& out, const TSignedRange& r)
516 {
517 return out << "Range [" << r.GetFrom() << ", " << r.GetTo() << "]";
518 }
519
operator ==(const TAlignColl & coll,const SARanges & expected)520 bool operator==(const TAlignColl& coll, const SARanges& expected)
521 {
522 if ( coll.size() != expected.size() ) {
523 return false;
524 }
525 auto it = coll.begin();
526 for ( auto& e : expected ) {
527 if ( e != *it++ ) {
528 return false;
529 }
530 }
531 for ( size_t i = 0; i < expected.size(); ++i ) {
532 if ( expected[i] != coll[i] ) { /* NCBI_FAKE_WARNING */
533 return false;
534 }
535 }
536 return true;
537 }
538
539 ///////////////////////////////////////////////////////////////////////////////
540 /// TAlignColl - Test Cases
541
542 BOOST_AUTO_TEST_SUITE(CAlignRangeCollection_Unit_Test)
543
544 /// insertion must be tested first as all other tests rely on insert()
BOOST_AUTO_TEST_CASE(AC_Test_Insert)545 BOOST_AUTO_TEST_CASE(AC_Test_Insert)
546 {
547 TAlignColl coll(0);
548 BOOST_CHECK_EQUAL(coll.empty(), true);
549
550 TAlignColl::const_iterator it = coll.insert(coll.end(), TAlignRange(501, 1501, 10, true));
551
552 BOOST_CHECK(it == coll.begin());
553 BOOST_CHECK_EQUAL(coll, SARanges({{501, 1501, 10, true}}));
554 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fDirect | TAlignColl::fNotValidated);
555 BOOST_CHECK_EQUAL(coll.empty(), false);
556
557 // insert empty range - this should have no effect
558 it = coll.insert(coll.begin(), TAlignRange(100, 100, 0, false));
559
560 BOOST_CHECK(it == coll.end());
561 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fDirect | TAlignColl::fNotValidated);
562
563 // insert a segment in the first position
564 it = coll.insert(coll.begin(), TAlignRange(1, 1001, 10, true));
565
566 BOOST_CHECK(it == coll.begin());
567 BOOST_CHECK_EQUAL(coll, SARanges({{1, 1001, 10, true}, {501, 1501, 10, true}}));
568 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fDirect | TAlignColl::fNotValidated);
569
570 it = coll.insert(coll.begin() + 1, TAlignRange(201, 1201, 10, true));
571
572 BOOST_CHECK(it == coll.begin() + 1);
573 BOOST_CHECK_EQUAL(coll, SARanges({ {1, 1001, 10, true}, {201, 1201, 10, true}, {501, 1501, 10, true} }));
574 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fDirect | TAlignColl::fNotValidated);
575
576 // reset
577 coll.clear();
578 BOOST_CHECK_EQUAL(coll.GetFlags(), 0);
579
580 coll.insert(coll.begin(), TAlignRange(1, 1001, 10, false));
581 coll.insert(coll.begin(), TAlignRange(101, 1101, 20, true));
582
583 SARange res_4[] = { {101, 1101, 20, true}, {1, 1001, 10, false} };
584 AC_Collection_Equals(coll, res_4, sizeof(res_4) / sizeof(SARange));
585 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fNotValidated | TAlignColl::fMixedDir );
586
587 coll.Validate();
588 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fInvalid | TAlignColl::fMixedDir |
589 TAlignColl::fUnsorted);
590 }
591
592
BOOST_AUTO_TEST_CASE(AC_Test_Constructors)593 BOOST_AUTO_TEST_CASE(AC_Test_Constructors)
594 {
595 // check state of an empty collection
596 TAlignColl coll_1;
597
598 BOOST_CHECK_EQUAL((int) coll_1.size(), 0);
599 BOOST_CHECK_EQUAL(coll_1.empty(), true);
600 BOOST_CHECK_EQUAL(coll_1.GetFlags(), TAlignColl::fKeepNormalized);
601
602 // add ranges
603 SARange ranges_1[] = { {101, 1101, 10, true}, {151, 1151, 20, true}, {201, 1201, 30, true} };
604 AC_AddToCollection(coll_1, ranges_1, sizeof(ranges_1) / sizeof(SARange));
605
606 BOOST_CHECK_EQUAL((int) coll_1.size(), 3);
607 BOOST_CHECK_EQUAL(coll_1.empty(), false);
608 BOOST_CHECK_EQUAL(coll_1.GetFlags(), TAlignColl::fKeepNormalized | TAlignColl::fDirect);
609
610 TAlignColl coll_2(coll_1);
611
612 AC_Collection_Equals(coll_1, ranges_1, sizeof(ranges_1) / sizeof(SARange));
613 AC_Collection_Equals(coll_2, ranges_1, sizeof(ranges_1) / sizeof(SARange));
614 }
615
616
BOOST_AUTO_TEST_CASE(AC_Test_Erase)617 BOOST_AUTO_TEST_CASE(AC_Test_Erase)
618 {
619 TAlignColl coll;
620
621 SARange ranges_1[] = { {101, 1101, 10, true}, {151, 1151, 15, true}, {201, 1201, 20, true} };
622 AC_AddToCollection(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
623
624 // erase second segment
625 TAlignColl::const_iterator it = coll.erase(coll.begin() + 1);
626
627 BOOST_CHECK(it == coll.begin() + 1);
628 SARange res_1[] = { {101, 1101, 10, true}, {201, 1201, 20, true} };
629 AC_Collection_Equals(coll, res_1, sizeof(res_1) / sizeof(SARange));
630
631 // erase first segment
632 it = coll.erase(coll.begin());
633
634 BOOST_CHECK(it == coll.begin());
635 SARange res_2[] = { {201, 1201, 20, true} };
636 AC_Collection_Equals(coll, res_2, sizeof(res_2) / sizeof(SARange));
637
638 // erase the remaining one
639 it = coll.erase(coll.begin());
640
641 BOOST_CHECK_EQUAL((int) coll.size(), 0);
642 BOOST_CHECK_EQUAL(coll.empty(), true);
643 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fKeepNormalized);
644 }
645
646
BOOST_AUTO_TEST_CASE(AC_Test_PushPop)647 BOOST_AUTO_TEST_CASE(AC_Test_PushPop)
648 {
649 TAlignColl coll(0);
650
651 coll.push_back(TAlignRange(1, 1201, 10, false));
652 coll.push_back(TAlignRange(101, 1101, 20, false));
653
654 SARange ranges_1[] = { {1, 1201, 10, false}, {101, 1101, 20, false} };
655 AC_Collection_Equals(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
656
657 coll.pop_back();
658 coll.push_back(TAlignRange(201, 1001, 30, false));
659
660 SARange ranges_2[] = { {1, 1201, 10, false}, {201, 1001, 30, false} };
661 AC_Collection_Equals(coll, ranges_2, sizeof(ranges_2) / sizeof(SARange));
662
663 coll.pop_back();
664
665 SARange ranges_3[] = { {1, 1201, 10, false} };
666 AC_Collection_Equals(coll, ranges_3, sizeof(ranges_3) / sizeof(SARange));
667
668 coll.pop_back();
669 BOOST_CHECK_EQUAL(coll.empty(), true);
670 }
671
672
673 /// Tests insert(), Validate(), Sort(), CombineAbutting() methods in a collection
674 /// that does not have fKeepNormalized flag set
BOOST_AUTO_TEST_CASE(AC_TestDenormalized)675 BOOST_AUTO_TEST_CASE(AC_TestDenormalized)
676 {
677 TAlignColl coll(0);
678
679 // Test Insertion
680 SARange ranges_1[] = { {101, 1001, 10, true}, {151, 1051, 50, true}, {111, 1011, 20, true} };
681 AC_AddToCollection(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
682
683 // the result must be identical to the input
684 AC_Collection_Equals(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
685 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fDirect | TAlignColl::fNotValidated);
686
687 SARange ranges_2[] = { {201, 1101, 50, true}, {1, 1, 100, true} };
688 AC_AddToCollection(coll, ranges_2, sizeof(ranges_2) / sizeof(SARange));
689
690 SARange res_2[] = { {101, 1001, 10, true}, {151, 1051, 50, true}, {111, 1011, 20, true},
691 {201, 1101, 50, true}, {1, 1, 100, true} };
692
693 AC_Collection_Equals(coll, res_2, sizeof(res_2) / sizeof(SARange));
694 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fDirect | TAlignColl::fNotValidated);
695
696 // Validate
697 coll.Validate();
698 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fDirect | TAlignColl::fInvalid |
699 TAlignColl::fUnsorted);
700
701 // Now Sorting
702 coll.Sort();
703
704 SARange res_3[] = { {1, 1, 100, true}, {101, 1001, 10, true}, {111, 1011, 20, true},
705 {151, 1051, 50, true}, {201, 1101, 50, true} };
706
707 AC_Collection_Equals(coll, res_3, sizeof(res_3) / sizeof(SARange));
708 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fDirect | TAlignColl::fNotValidated |
709 TAlignColl::fInvalid);
710
711 // Validate
712 coll.Validate();
713 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fDirect | TAlignColl::fInvalid | TAlignColl::fAbutting);
714
715 // Merge
716 coll.CombineAbutting();
717
718 SARange res_4[] = { {1, 1, 100, true}, {101, 1001, 30, true}, {151, 1051, 100, true} };
719 AC_Collection_Equals(coll, res_4, sizeof(res_4) / sizeof(SARange));
720 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fDirect | TAlignColl::fInvalid |
721 TAlignColl::fNotValidated);
722
723 coll.Validate();
724 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fDirect);
725
726 // test overlapping
727 TAlignRange r_1(5000, 110, 10, true); // overlaps with the second segement on the second seq
728 // this is fine (by design )
729 coll.insert(r_1);
730 coll.Validate();
731 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fDirect); // Perfect
732
733 TAlignRange r_2(110, 5000, 10, true); // this should produce overlap
734 coll.insert(r_1);
735 coll.Validate();
736 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fDirect | TAlignColl::fInvalid |
737 TAlignColl::fOverlap);
738 }
739
740
BOOST_AUTO_TEST_CASE(AC_Test_Remove)741 BOOST_AUTO_TEST_CASE(AC_Test_Remove)
742 {
743 TAlignColl coll(0);
744
745 // Test Insertion
746 SARange ranges_1[] = { {101, 1001, 10, true}, {201, 1201, 20, false}, {301, 1301, 30, true} };
747 AC_AddToCollection(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
748
749 coll.erase(coll.begin() + 1);
750
751 SARange res_1[] = { {101, 1001, 10, true}, {301, 1301, 30, true} };
752 AC_Collection_Equals(coll, res_1, sizeof(res_1) / sizeof(SARange));
753 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fMixedDir | TAlignColl::fNotValidated);
754
755 coll.erase(coll.begin() + 1);
756
757 SARange res_2[] = { {101, 1001, 10, true} };
758 AC_Collection_Equals(coll, res_2, sizeof(res_2) / sizeof(SARange));
759 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fMixedDir | TAlignColl::fNotValidated);
760
761 coll.erase(coll.begin());
762
763 BOOST_CHECK_EQUAL(coll.empty(), true);
764 BOOST_CHECK_EQUAL(coll.GetFlags(), 0);
765
766 // check thta no exceptions is thrown
767 coll.erase(coll.end());
768 coll.erase(coll.begin());
769 }
770
771
BOOST_AUTO_TEST_CASE(AC_TestDirections)772 BOOST_AUTO_TEST_CASE(AC_TestDirections)
773 {
774 SARange ranges_1[] = { {101, 1001, 10, true} };
775
776 TAlignColl coll_1(0); // reset fKeepNormalized
777 AC_AddToCollection(coll_1, ranges_1, sizeof(ranges_1) / sizeof(SARange));
778 coll_1.Validate();
779 BOOST_CHECK_EQUAL(coll_1.GetFlags(), TAlignColl::fDirect);
780
781
782 SARange ranges_2[] = { {1, 1, 10, false} };
783
784 TAlignColl coll_2(0); // reset fKeepNormalized
785 AC_AddToCollection(coll_2, ranges_2, sizeof(ranges_2) / sizeof(SARange));
786 BOOST_CHECK_EQUAL(coll_2.GetFlags(), TAlignColl::fReversed | TAlignColl::fNotValidated);
787
788 TAlignRange r_1(201, 1201, 20, false);
789
790 coll_1.insert(r_1);
791 BOOST_CHECK_EQUAL(coll_1.GetFlags(), TAlignColl::fMixedDir | TAlignColl::fNotValidated);
792 coll_1.Validate();
793 BOOST_CHECK_EQUAL(coll_1.GetFlags(), TAlignColl::fMixedDir | TAlignColl::fInvalid);
794
795 coll_2.insert(r_1);
796 BOOST_CHECK_EQUAL(coll_2.GetFlags(), TAlignColl::fReversed | TAlignColl::fNotValidated);
797 coll_2.Validate();
798 BOOST_CHECK_EQUAL(coll_2.GetFlags(), TAlignColl::fReversed);
799 }
800
801
BOOST_AUTO_TEST_CASE(AC_TestNormalized_Strict)802 BOOST_AUTO_TEST_CASE(AC_TestNormalized_Strict)
803 {
804 {
805 TAlignColl coll(TAlignColl::fKeepNormalized);
806
807 SARange ranges_1[] = { {101, 101, 20, true}, {201, 201, 50, true}, {1, 1, 10, true} };
808 AC_AddToCollection(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
809
810 // add - results should be sorted, validated and valid
811 BOOST_CHECK_EQUAL(coll, SARanges({ {1, 1, 10, true}, {101, 101, 20, true}, {201, 201, 50, true} }));
812 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fKeepNormalized | TAlignColl::fDirect);
813
814 // add adjacent segment - it should merge automatically
815 TAlignRange r_1(121, 121, 30, true);
816 coll.insert(r_1);
817
818 BOOST_CHECK_EQUAL(coll, SARanges({ {1, 1, 10, true}, {101, 101, 50, true}, {201, 201, 50, true} }));
819 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fKeepNormalized | TAlignColl::fDirect);
820
821 // add a segment with wrong direction - becomes invalid
822 TAlignRange r_2(1000, 1000, 10, false);
823 BOOST_CHECK_THROW(coll.insert(r_2), CAlignRangeCollException);
824
825 BOOST_CHECK_EQUAL(coll, SARanges({ {1, 1, 10, true}, {101, 101, 50, true}, {201, 201, 50, true}, {1000, 1000, 10, false} }));
826 BOOST_CHECK_EQUAL(coll.GetFlags(), TAlignColl::fKeepNormalized | TAlignColl::fMixedDir | TAlignColl::fInvalid);
827 }
828 {
829 TAlignColl coll(TAlignColl::fKeepNormalized);
830
831 SARange ranges_1[] = { {1, 1, 10, true}, {201, 201, 50, true}, };
832 AC_AddToCollection(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
833
834 // add Overlapping segment - becomes invalid
835 TAlignRange r(210, 500, 30, true);
836 BOOST_CHECK_THROW(coll.insert(r), CAlignRangeCollException);
837
838 BOOST_CHECK_EQUAL(coll, SARanges({ {1, 1, 10, true}, {201, 201, 50, true}, {210, 500, 30, true} }));
839 BOOST_CHECK_EQUAL(coll.GetFlags(),
840 TAlignColl::fKeepNormalized | TAlignColl::fDirect |
841 TAlignColl::fOverlap | TAlignColl::fInvalid);
842
843 }
844 {
845 TAlignColl coll(TAlignColl::fKeepNormalized);
846
847 SARange ranges_1[] = { {1, 1, 10, true}, {201, 201, 50, true}, };
848 AC_AddToCollection(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
849
850 // add Overlapping Reversed segment - both fOverlap & fMixedDir must be flagged
851 TAlignRange r(210, 500, 30, false);
852 BOOST_CHECK_THROW(coll.insert(r), CAlignRangeCollException);
853
854 BOOST_CHECK_EQUAL(coll, SARanges({ {1, 1, 10, true}, {201, 201, 50, true}, {210, 500, 30, false} }));
855 BOOST_CHECK_EQUAL(coll.GetFlags(),
856 TAlignColl::fKeepNormalized | TAlignColl::fMixedDir |
857 TAlignColl::fOverlap | TAlignColl::fInvalid);
858 }
859
860
861 {
862 // if 'from' are equal new segment is inserted before old ones
863 TAlignColl coll(TAlignColl::fKeepNormalized);
864
865 SARange ranges_1[] = { {1, 1, 10, true}, {201, 201, 50, true}, };
866 AC_AddToCollection(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
867
868 // add Overlapping segment - becomes invalid
869 TAlignRange r(201, 500, 30, true);
870 BOOST_CHECK_THROW(coll.insert(r), CAlignRangeCollException);
871
872 BOOST_CHECK_EQUAL(coll, SARanges({ {1, 1, 10, true}, {201, 500, 30, true}, {201, 201, 50, true} }));
873 BOOST_CHECK_EQUAL(coll.GetFlags(),
874 TAlignColl::fKeepNormalized | TAlignColl::fDirect |
875 TAlignColl::fOverlap | TAlignColl::fInvalid);
876
877 }
878 {
879 // if 'from' are equal new segment is inserted before old ones
880 TAlignColl coll(TAlignColl::fKeepNormalized);
881
882 SARange ranges_1[] = { {1, 1, 10, true}, {201, 201, 50, true}, };
883 AC_AddToCollection(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
884
885 // add Overlapping Reversed segment - both fOverlap & fMixedDir must be flagged
886 TAlignRange r(201, 500, 300, false);
887 BOOST_CHECK_THROW(coll.insert(r), CAlignRangeCollException);
888
889 BOOST_CHECK_EQUAL(coll, SARanges({ {1, 1, 10, true}, {201, 500, 300, false}, {201, 201, 50, true} }));
890 BOOST_CHECK_EQUAL(coll.GetFlags(),
891 TAlignColl::fKeepNormalized | TAlignColl::fMixedDir |
892 TAlignColl::fOverlap | TAlignColl::fInvalid);
893 }
894 }
895
896
AC_CheckBounds(const TAlignColl & coll,const TSignedRange & r_1,const TSignedRange &)897 void AC_CheckBounds(const TAlignColl& coll, const TSignedRange& r_1, const TSignedRange& /*r_2*/)
898 {
899 BOOST_CHECK_EQUAL(coll.GetFirstRange(), r_1);
900 BOOST_CHECK_EQUAL(coll.GetFirstFrom(), r_1.GetFrom());
901 BOOST_CHECK_EQUAL(coll.GetFirstTo(), r_1.GetTo());
902 BOOST_CHECK_EQUAL(coll.GetFirstToOpen(), r_1.GetToOpen());
903 }
904
905
BOOST_AUTO_TEST_CASE(AC_TestBounds)906 BOOST_AUTO_TEST_CASE(AC_TestBounds)
907 {
908 SARange ranges_1[] = { {1, 1001, 10, true}, {101, 1101, 50, true}, {201, 1201, 50, true} };
909 TAlignColl coll; // normalized
910 AC_AddToCollection(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
911
912 TSignedRange r_1(1, 250), r_2(1001, 1250);
913 AC_CheckBounds(coll, r_1, r_2);
914
915 coll.clear();
916 SARange ranges_2[] = { {1, 1201, 10, false}, {101, 1101, 50, false}, {201, 1001, 50, false} };
917 AC_AddToCollection(coll, ranges_2, sizeof(ranges_2) / sizeof(SARange));
918 AC_CheckBounds(coll, r_1, r_2);
919 }
920
921
922 // test CAlignRangeCollection::find(), find_2()
BOOST_AUTO_TEST_CASE(AC_TestFind)923 BOOST_AUTO_TEST_CASE(AC_TestFind)
924 {
925 {
926 // test direct
927 SARange ranges_1[] = { {1, 1, 10, true}, {101, 101, 50, true}, {201, 201, 50, true} };
928
929 TAlignColl coll; // normalized
930 AC_AddToCollection(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
931
932 TAlignColl::const_iterator it = coll.find(5);
933 BOOST_CHECK(it == coll.begin());
934
935 it = coll.find(120);
936 BOOST_CHECK(it == coll.begin() + 1);
937
938 // first and last positions
939 it = coll.find(201);
940 BOOST_CHECK(it == coll.begin() + 2);
941 it = coll.find(250);
942 BOOST_CHECK(it == coll.begin() + 2);
943
944 // invalid positions
945 it = coll.find(0);
946 BOOST_CHECK(it == coll.end());
947 it = coll.find(200);
948 BOOST_CHECK(it == coll.end());
949 it = coll.find(5000);
950 BOOST_CHECK(it == coll.end());
951 }
952 // test find with adjacent
953 {
954 TAlignColl coll(TAlignColl::fKeepNormalized | TAlignColl::fAllowAbutting);
955
956 SARange ranges_1[] = { {101, 101, 10, true}, {111, 111, 20, true}, {132, 132, 69, true} };
957 AC_AddToCollection(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
958
959 TAlignColl::const_iterator it = coll.find(110);
960 BOOST_CHECK(it == coll.begin());
961
962 it = coll.find(111);
963 BOOST_CHECK(it == coll.begin() + 1);
964 it = coll.find(130);
965 BOOST_CHECK(it == coll.begin() + 1);
966
967 it = coll.find(131);
968 BOOST_CHECK(it == coll.end()); // gap here
969 it = coll.find(132);
970 BOOST_CHECK(it == coll.begin() + 2);
971 }
972 // test reversed
973 {
974 TAlignColl coll;
975
976 SARange ranges_1[] = { {101, 1301, 10, false}, {201, 1201, 20, false}, {301, 1101, 50, false} };
977 AC_AddToCollection(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
978
979 TAlignColl::const_iterator it = coll.find(105);
980 BOOST_CHECK(it == coll.begin());
981
982 // edeges of the second segment
983 it = coll.find(201);
984 BOOST_CHECK(it == coll.begin() + 1);
985 it = coll.find(220);
986 BOOST_CHECK(it == coll.begin() + 1);
987
988 it = coll.find(350);
989 BOOST_CHECK(it == coll.begin() + 2);
990 it = coll.find(351);
991 BOOST_CHECK(it == coll.end());
992 }
993 // TODO - find in overlapped
994 }
995
996
BOOST_AUTO_TEST_CASE(AC_Test_GetSecondByFirst)997 BOOST_AUTO_TEST_CASE(AC_Test_GetSecondByFirst)
998 {
999 {
1000 TAlignColl coll;
1001
1002 // 101-----110 201-----220 301-----350 ->
1003 // 1101---1110 1201---1220 1101---1150 ->
1004 SARange ranges_1[] = { {101, 1101, 10, true}, {201, 1201, 20, true}, {301, 1101, 50, true} };
1005 AC_AddToCollection(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
1006
1007 TSignedSeqPos pos, pos_2;
1008 pos = coll.GetSecondPosByFirstPos(100); // out of bounds to the left
1009 BOOST_CHECK_EQUAL(pos, -1);
1010
1011 pos = coll.GetSecondPosByFirstPos(101);
1012 BOOST_CHECK_EQUAL(pos, 1101);
1013
1014 pos = coll.GetSecondPosByFirstPos(220);
1015 BOOST_CHECK_EQUAL(pos, 1220);
1016
1017 pos = coll.GetSecondPosByFirstPos(351); // out of bounds to the right
1018 BOOST_CHECK_EQUAL(pos, -1);
1019
1020 // use "seek" option - eForward, eRight
1021 pos = coll.GetSecondPosByFirstPos(0, TAlignColl::eForward);
1022 pos_2 = coll.GetSecondPosByFirstPos(0, TAlignColl::eRight);
1023 BOOST_CHECK_EQUAL(pos, 1101); // position closest to the right
1024 BOOST_CHECK_EQUAL(pos_2, 1101);
1025
1026 pos = coll.GetSecondPosByFirstPos(150, TAlignColl::eForward);
1027 pos_2 = coll.GetSecondPosByFirstPos(150, TAlignColl::eRight);
1028 BOOST_CHECK_EQUAL(pos, 1201); // position closest to the right
1029 BOOST_CHECK_EQUAL(pos_2, 1201);
1030
1031 pos = coll.GetSecondPosByFirstPos(450, TAlignColl::eForward);
1032 pos_2 = coll.GetSecondPosByFirstPos(450, TAlignColl::eRight);
1033 BOOST_CHECK_EQUAL(pos, -1); // out of bounds
1034 BOOST_CHECK_EQUAL(pos_2, -1);
1035
1036 // eBackwards, eLeft
1037 pos = coll.GetSecondPosByFirstPos(150, TAlignColl::eBackwards);
1038 pos_2 = coll.GetSecondPosByFirstPos(150, TAlignColl::eLeft);
1039 BOOST_CHECK_EQUAL(pos, 1110); // position closest to the left
1040 BOOST_CHECK_EQUAL(pos_2, 1110);
1041
1042 pos = coll.GetSecondPosByFirstPos(5000, TAlignColl::eBackwards);
1043 pos_2 = coll.GetSecondPosByFirstPos(5000, TAlignColl::eLeft);
1044 BOOST_CHECK_EQUAL(pos, 1150); // position closest to the left
1045 BOOST_CHECK_EQUAL(pos_2, 1150);
1046
1047 pos = coll.GetSecondPosByFirstPos(10, TAlignColl::eBackwards);
1048 pos_2 = coll.GetSecondPosByFirstPos(10, TAlignColl::eLeft);
1049 BOOST_CHECK_EQUAL(pos, -1); // out of bounds
1050 BOOST_CHECK_EQUAL(pos_2, -1);
1051 }
1052 // reversed
1053 {
1054 TAlignColl coll;
1055
1056 // 1------10 51-----70 ->
1057 // <- 260---251 220---201
1058 SARange ranges_1[] = { {1, 251, 10, false}, {51, 201, 20, false}};
1059 AC_AddToCollection(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
1060
1061 TSignedSeqPos pos, pos_2;
1062 pos = coll.GetSecondPosByFirstPos(0); // out of bounds to the left
1063 BOOST_CHECK_EQUAL(pos, -1);
1064
1065 pos = coll.GetSecondPosByFirstPos(71); // out of bounds to the right
1066 BOOST_CHECK_EQUAL(pos, -1);
1067
1068 // inside a segment
1069 pos = coll.GetSecondPosByFirstPos(1);
1070 BOOST_CHECK_EQUAL(pos, 260);
1071 pos = coll.GetSecondPosByFirstPos(10);
1072 BOOST_CHECK_EQUAL(pos, 251);
1073
1074 pos = coll.GetSecondPosByFirstPos(61);
1075 BOOST_CHECK_EQUAL(pos, 210);
1076
1077 // use "seek" option - eForward, eRight
1078 pos = coll.GetSecondPosByFirstPos(0, TAlignColl::eForward);
1079 pos_2 = coll.GetSecondPosByFirstPos(0, TAlignColl::eRight);
1080 BOOST_CHECK_EQUAL(pos, 260); // position closest to the right
1081 BOOST_CHECK_EQUAL(pos_2, 260);
1082
1083 pos = coll.GetSecondPosByFirstPos(30, TAlignColl::eForward);
1084 pos_2 = coll.GetSecondPosByFirstPos(30, TAlignColl::eRight);
1085 BOOST_CHECK_EQUAL(pos, 220); // position closest to the right
1086 BOOST_CHECK_EQUAL(pos_2, 220);
1087
1088 pos = coll.GetSecondPosByFirstPos(130, TAlignColl::eForward);
1089 pos_2 = coll.GetSecondPosByFirstPos(130, TAlignColl::eRight);
1090 BOOST_CHECK_EQUAL(pos, -1); // out of bounds
1091 BOOST_CHECK_EQUAL(pos_2, -1);
1092
1093 // eBackwards, eLeft
1094 pos = coll.GetSecondPosByFirstPos(30, TAlignColl::eBackwards);
1095 pos_2 = coll.GetSecondPosByFirstPos(30, TAlignColl::eLeft);
1096 BOOST_CHECK_EQUAL(pos, 251); // position closest to the left
1097 BOOST_CHECK_EQUAL(pos_2, 251);
1098
1099 pos = coll.GetSecondPosByFirstPos(5000, TAlignColl::eBackwards);
1100 pos_2 = coll.GetSecondPosByFirstPos(5000, TAlignColl::eLeft);
1101 BOOST_CHECK_EQUAL(pos, 201); // position closest to the left
1102 BOOST_CHECK_EQUAL(pos_2, 201);
1103
1104 pos = coll.GetSecondPosByFirstPos(0, TAlignColl::eBackwards);
1105 pos_2 = coll.GetSecondPosByFirstPos(0, TAlignColl::eLeft);
1106 BOOST_CHECK_EQUAL(pos, -1); // out of bounds
1107 BOOST_CHECK_EQUAL(pos_2, -1);
1108 }
1109 }
1110
1111
BOOST_AUTO_TEST_CASE(AC_Test_GetFirstBySecond)1112 BOOST_AUTO_TEST_CASE(AC_Test_GetFirstBySecond)
1113 {
1114 {
1115 TAlignColl coll;
1116
1117 // 101-----110 201-----220 301-----350 ->
1118 // 1101---1110 1201---1220 1301---1350 ->
1119 SARange ranges_1[] = { {101, 1101, 10, true}, {201, 1201, 20, true}, {301, 1301, 50, true} };
1120 AC_AddToCollection(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
1121
1122 TSignedSeqPos pos, pos_2;
1123 pos = coll.GetFirstPosBySecondPos(1100); // out of bounds to the left
1124 BOOST_CHECK_EQUAL(pos, -1);
1125
1126 pos = coll.GetFirstPosBySecondPos(1351); // out of bounds to the right
1127 BOOST_CHECK_EQUAL(pos, -1);
1128
1129 pos = coll.GetFirstPosBySecondPos(1201);
1130 BOOST_CHECK_EQUAL(pos, 201);
1131
1132 pos = coll.GetFirstPosBySecondPos(1220);
1133 BOOST_CHECK_EQUAL(pos, 220);
1134
1135 pos = coll.GetFirstPosBySecondPos(1310);
1136 BOOST_CHECK_EQUAL(pos, 310);
1137
1138 // use "seek" option - eForward, eRight
1139 pos = coll.GetFirstPosBySecondPos(0, TAlignColl::eForward);
1140 pos_2 = coll.GetFirstPosBySecondPos(0, TAlignColl::eRight);
1141 BOOST_CHECK_EQUAL(pos, 101); // position closest to the right
1142 BOOST_CHECK_EQUAL(pos_2, 101);
1143
1144 pos = coll.GetFirstPosBySecondPos(1150, TAlignColl::eForward);
1145 pos_2 = coll.GetFirstPosBySecondPos(1150, TAlignColl::eRight);
1146 BOOST_CHECK_EQUAL(pos, 201); // position closest to the right
1147 BOOST_CHECK_EQUAL(pos_2, 201);
1148
1149 pos = coll.GetFirstPosBySecondPos(2150, TAlignColl::eForward);
1150 pos_2 = coll.GetFirstPosBySecondPos(2150, TAlignColl::eRight);
1151 BOOST_CHECK_EQUAL(pos, -1); // out of bounds
1152 BOOST_CHECK_EQUAL(pos_2, -1);
1153
1154 // eBackwards, eLeft
1155 pos = coll.GetFirstPosBySecondPos(1150, TAlignColl::eBackwards);
1156 pos_2 = coll.GetFirstPosBySecondPos(1150, TAlignColl::eLeft);
1157 BOOST_CHECK_EQUAL(pos, 110); // position closest to the left
1158 BOOST_CHECK_EQUAL(pos_2, 110);
1159
1160 pos = coll.GetFirstPosBySecondPos(5000, TAlignColl::eBackwards);
1161 pos_2 = coll.GetFirstPosBySecondPos(5000, TAlignColl::eLeft);
1162 BOOST_CHECK_EQUAL(pos, 350); // position closest to the left
1163 BOOST_CHECK_EQUAL(pos_2, 350);
1164
1165 pos = coll.GetFirstPosBySecondPos(100, TAlignColl::eBackwards);
1166 pos_2 = coll.GetFirstPosBySecondPos(100, TAlignColl::eLeft);
1167 BOOST_CHECK_EQUAL(pos, -1); // out of bounds
1168 BOOST_CHECK_EQUAL(pos_2, -1);
1169 }
1170 // reversed
1171 {
1172 TAlignColl coll;
1173
1174 // 1------10 51-----70 ->
1175 // <- 260---251 220---201
1176 SARange ranges_1[] = { {1, 251, 10, false}, {51, 201, 20, false}};
1177 AC_AddToCollection(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
1178
1179 TSignedSeqPos pos, pos_2;
1180 pos = coll.GetFirstPosBySecondPos(200); // out of bounds to the left
1181 BOOST_CHECK_EQUAL(pos, -1);
1182
1183 pos = coll.GetFirstPosBySecondPos(261); // out of bounds to the right
1184 BOOST_CHECK_EQUAL(pos, -1);
1185
1186 // inside a segment
1187 pos = coll.GetFirstPosBySecondPos(201);
1188 BOOST_CHECK_EQUAL(pos, 70);
1189 pos = coll.GetFirstPosBySecondPos(220);
1190 BOOST_CHECK_EQUAL(pos, 51);
1191
1192 pos = coll.GetFirstPosBySecondPos(255);
1193 BOOST_CHECK_EQUAL(pos, 6);
1194
1195 // use "seek" option - eForward, eLeft
1196 pos = coll.GetFirstPosBySecondPos(0, TAlignColl::eForward);
1197 pos_2 = coll.GetFirstPosBySecondPos(0, TAlignColl::eLeft);
1198 BOOST_CHECK_EQUAL(pos, 70); // position closest to the left
1199 BOOST_CHECK_EQUAL(pos_2, pos);
1200
1201 pos = coll.GetFirstPosBySecondPos(230, TAlignColl::eForward);
1202 pos_2 = coll.GetFirstPosBySecondPos(230, TAlignColl::eLeft);
1203 BOOST_CHECK_EQUAL(pos, 10); // position closest to the left
1204 BOOST_CHECK_EQUAL(pos_2, 10);
1205
1206 pos = coll.GetFirstPosBySecondPos(1200, TAlignColl::eForward);
1207 pos_2 = coll.GetFirstPosBySecondPos(1200, TAlignColl::eLeft);
1208 BOOST_CHECK_EQUAL(pos, -1); // out of bounds
1209 BOOST_CHECK_EQUAL(pos_2, -1);
1210
1211 // eBackwards, eRight
1212 pos = coll.GetFirstPosBySecondPos(230, TAlignColl::eBackwards);
1213 pos_2 = coll.GetFirstPosBySecondPos(230, TAlignColl::eRight);
1214 BOOST_CHECK_EQUAL(pos, 51); // position closest to the right
1215 BOOST_CHECK_EQUAL(pos_2, 51);
1216
1217 pos = coll.GetFirstPosBySecondPos(5000, TAlignColl::eBackwards);
1218 pos_2 = coll.GetFirstPosBySecondPos(5000, TAlignColl::eRight);
1219 BOOST_CHECK_EQUAL(pos, 1); // position closest to the right
1220 BOOST_CHECK_EQUAL(pos_2, 1);
1221
1222 pos = coll.GetFirstPosBySecondPos(50, TAlignColl::eBackwards);
1223 pos_2 = coll.GetFirstPosBySecondPos(50, TAlignColl::eRight);
1224 BOOST_CHECK_EQUAL(pos, -1); // out of bounds
1225 BOOST_CHECK_EQUAL(pos_2, -1);
1226 }
1227 }
1228
1229
BOOST_AUTO_TEST_CASE(AC_Test_Extender)1230 BOOST_AUTO_TEST_CASE(AC_Test_Extender)
1231 {
1232 {
1233 TAlignColl coll;
1234
1235 SARange ranges_1[] = { {101, 1101, 10, true}, {201, 1201, 20, true}, {301, 1301, 30, true} };
1236 AC_AddToCollection(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
1237
1238 typedef CAlignRangeCollExtender<TAlignColl> TExtender;
1239 TExtender ext(coll);
1240
1241 BOOST_CHECK_EQUAL(ext.GetSecondFrom(), 1101);
1242 BOOST_CHECK_EQUAL(ext.GetSecondTo(), 1330);
1243 BOOST_CHECK_EQUAL(ext.GetSecondToOpen(), 1331);
1244 BOOST_CHECK_EQUAL(ext.GetSecondLength(), 230);
1245 BOOST_CHECK_EQUAL(ext.GetSecondRange(), CRange<TSignedSeqPos>(1101, 1330));
1246
1247 TExtender::const_iterator it = ext.FindOnSecond(1100); // out of range on the left
1248 BOOST_CHECK(it == ext.end());
1249
1250 it = ext.FindOnSecond(1331); // out of range on the right
1251 BOOST_CHECK(it == ext.end());
1252
1253 it = ext.FindOnSecond(1200); // gap
1254 BOOST_CHECK(it == ext.end());
1255 it = ext.FindOnSecond(1221); // gap
1256 BOOST_CHECK(it == ext.end());
1257
1258
1259 it = ext.FindOnSecond(1101); // first position on the first segment
1260 const TAlignRange* r = it->second;
1261 BOOST_CHECK_EQUAL(*r, *coll.begin());
1262
1263 it = ext.FindOnSecond(1330); // last position on the last segment
1264 r = it->second;
1265 BOOST_CHECK_EQUAL(*r, *(coll.begin() + 2));
1266
1267 it = ext.FindOnSecond(1210); // in the middle of the second segment
1268 r = it->second;
1269 BOOST_CHECK_EQUAL(*r, *(coll.begin() + 1));
1270 }
1271 // now test relaxed collection unsorted and with overlaps
1272 {
1273 TAlignColl coll(0);
1274
1275 SARange ranges_1[] = { {111, 1111, 30, true}, {101, 1101, 20, true}, {1, 1001, 10, true}, };
1276 AC_AddToCollection(coll, ranges_1, sizeof(ranges_1) / sizeof(SARange));
1277
1278 typedef CAlignRangeCollExtender<TAlignColl> TExtender;
1279 TExtender ext(coll);
1280
1281 BOOST_CHECK_EQUAL(ext.GetSecondFrom(), 1001);
1282 BOOST_CHECK_EQUAL(ext.GetSecondTo(), 1140);
1283 BOOST_CHECK_EQUAL(ext.GetSecondToOpen(), 1141);
1284 BOOST_CHECK_EQUAL(ext.GetSecondLength(), 140);
1285 BOOST_CHECK_EQUAL(ext.GetSecondRange(), CRange<TSignedSeqPos>(1001, 1140));
1286
1287 TExtender::const_iterator it = ext.FindOnSecond(1000); // out of range on the left
1288 BOOST_CHECK(it == ext.end());
1289
1290 it = ext.FindOnSecond(1141); // out of range on the right
1291 BOOST_CHECK(it == ext.end());
1292
1293 it = ext.FindOnSecond(1011); // gap
1294 BOOST_CHECK(it == ext.end());
1295 it = ext.FindOnSecond(1100); // gap
1296 BOOST_CHECK(it == ext.end());
1297
1298
1299 it = ext.FindOnSecond(1001);
1300 const TAlignRange* r = it->second;
1301 BOOST_CHECK_EQUAL(r->GetFirstFrom(), 1);
1302
1303 it = ext.FindOnSecond(1105);
1304 r = it->second;
1305 BOOST_CHECK_EQUAL(r->GetFirstFrom(), 101);
1306
1307 it = ext.FindOnSecond(1111);
1308 r = it->second;
1309 BOOST_CHECK_EQUAL(r->GetFirstFrom(), 101); // the first of overlapped segments
1310
1311 it++;
1312 BOOST_CHECK(it != ext.end());
1313 r = it->second;
1314 BOOST_CHECK_EQUAL(r->GetFirstFrom(), 111); // the next
1315
1316 it = ext.FindOnSecond(1130);
1317 r = it->second;
1318 BOOST_CHECK_EQUAL(r->GetFirstFrom(), 111);
1319 }
1320 }
1321
BOOST_AUTO_TEST_SUITE_END()1322 BOOST_AUTO_TEST_SUITE_END()
1323
1324 END_NCBI_SCOPE
1325
1326 ///////////////////////////////////////////////////////////////////////////////
1327 /// main entry point for tests
1328
1329 NCBITEST_AUTO_INIT()
1330 {
1331 #if 0
1332 // Historic setup, disabled for the sake of uniformity; can still
1333 // be reenabled at runtime by means of the usual flags or env. vars.
1334 typedef boost::unit_test_framework::unit_test_log_t TLog;
1335 TLog& log = boost::unit_test_framework::unit_test_log;
1336 static std::ofstream out("res.xml"); //TODO
1337 log.set_stream(out);
1338 log.set_format(boost::unit_test_framework::XML);
1339 log.set_threshold_level(boost::unit_test_framework::log_test_units);
1340 #endif
1341
1342 boost::unit_test::framework::master_test_suite().p_name->assign
1343 ("UTIL Align Range, Collection Unit Test.");
1344 }
1345