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