1 //==============================================================================
2 //
3 //  This file is part of GPSTk, the GPS Toolkit.
4 //
5 //  The GPSTk is free software; you can redistribute it and/or modify
6 //  it under the terms of the GNU Lesser General Public License as published
7 //  by the Free Software Foundation; either version 3.0 of the License, or
8 //  any later version.
9 //
10 //  The GPSTk is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU Lesser General Public License for more details.
14 //
15 //  You should have received a copy of the GNU Lesser General Public
16 //  License along with GPSTk; if not, write to the Free Software Foundation,
17 //  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 //
19 //  This software was developed by Applied Research Laboratories at the
20 //  University of Texas at Austin.
21 //  Copyright 2004-2020, The Board of Regents of The University of Texas System
22 //
23 //==============================================================================
24 
25 //==============================================================================
26 //
27 //  This software was developed by Applied Research Laboratories at the
28 //  University of Texas at Austin, under contract to an agency or agencies
29 //  within the U.S. Department of Defense. The U.S. Government retains all
30 //  rights to use, duplicate, distribute, disclose, or release this software.
31 //
32 //  Pursuant to DoD Directive 523024
33 //
34 //  DISTRIBUTION STATEMENT A: This software has been approved for public
35 //                            release, distribution is unlimited.
36 //
37 //==============================================================================
38 
39 #include "FileFilter.hpp"
40 #include "TestUtil.hpp"
41 #include <algorithm>
42 #include <iostream>
43 #include <list>
44 
45 using namespace std;
46 using namespace gpstk;
47 
48 class FileFilter_T
49 {
50 public:
51 
52       // constructor
FileFilter_T()53    FileFilter_T() { init(); }
54 
55       // desructor
~FileFilter_T()56    ~FileFilter_T() { cleanup(); }
57 
58       // initialize tests
59    void init();
60 
61       // remove file system objectst created during tests
62    void cleanup();
63 
64       // test creation of an initialization of FileFilter objects
65       // @return  number of failures, i.e., 0=PASS, !0=FAIL
66    int testInitialization();
67 
68       // test addData(), getData(), getDataCount(), empty(), and clear()
69       // @return  number of failures, i.e., 0=PASS, !0=FAIL
70    int testData();
71 
72    int testBeginEnd();
73    int testFrontBack();
74    int testBack();
75    int testFilter();
76    int testSort();
77    int testMerge();
78    int testTouch();
79    int testUnique();
80    int testDiff();
81    int testFindAll();
82 
83 private:
84 
85       // FileFilter Test Data - dummy data class with which to run tests
86    class FFTData : public FFData
87    {
88    public:
FFTData(int val)89       FFTData(int val) : value(val) {}
~FFTData()90       ~FFTData() {}
91 
92       int  value;
93 
94    private:
95 
reallyGetRecord(FFStream & s)96       virtual void reallyGetRecord(FFStream& s)
97       { /* do nothing */ }
98 
99          /// Does the actual writing from the stream into this FFData object.
reallyPutRecord(FFStream & s) const100       virtual void reallyPutRecord(FFStream& s) const
101       { /* do nothing */ }
102 
103    }; // class Dummy
104 
105    typedef list<FFTData>  FFTDataList;
106 
107       // Unary predicate that returns true for data that has an even value
108    struct IsEven
109    {
110       bool operator() (const FFTData& fftd);
111    };
112 
113       // Unary predicate that returns true for data that has a value > 999
114    struct Above999
115    {
116       bool operator() (const FFTData& fftd);
117    };
118 
119       // Unary operation that doubles a data element if it is divisible by 5
120       // and returns true.  Elements not divisible by 5 are unchanged
121       // and false is returned.
122    struct DoubleFives
123    {
124       bool operator() (FFTData& fftd);
125    };
126 
127       // Binary predicate that implements "less-than" for data values
128    struct LessThan
129    {
130       bool operator() (const FFTData& left, const FFTData& right) const;
131    };
132 
133       // Binary predicate that implements "equal" for data values
134    struct Equal
135    {
136       bool operator() (const FFTData& left, const FFTData& right) const;
137    };
138 
139       // emit a list of objects to standard output
140       // @param list objects to emit
141    void dump(const FFTDataList& list);
142 
143    FFTDataList  sampleData;
144 
145 }; // class FileFilter_T
146 
147 
148 //---------------------------------------------------------------------------
operator ()(const FFTData & fftd)149 bool FileFilter_T :: IsEven :: operator() (const FFTData& fftd)
150 {
151    return (0 == (fftd.value % 2) );
152 }
153 
154 
155 //---------------------------------------------------------------------------
operator ()(const FFTData & fftd)156 bool FileFilter_T :: Above999 :: operator() (const FFTData& fftd)
157 {
158    return (fftd.value > 999);
159 }
160 
161 
162 //---------------------------------------------------------------------------
operator ()(FFTData & fftd)163 bool FileFilter_T :: DoubleFives :: operator() (FFTData& fftd)
164 {
165    if (0 == (fftd.value % 5) )
166    {
167       fftd.value *= 2;
168       return true;
169    }
170    return false;
171 }
172 
173 
174 //---------------------------------------------------------------------------
operator ()(const FFTData & left,const FFTData & right) const175 bool FileFilter_T :: LessThan :: operator() (const FFTData& left, const FFTData& right) const
176 {
177    return (left.value < right.value);
178 }
179 
180 
181 //---------------------------------------------------------------------------
operator ()(const FFTData & left,const FFTData & right) const182 bool FileFilter_T :: Equal :: operator() (const FFTData& left, const FFTData& right) const
183 {
184    return (left.value == right.value);
185 }
186 
187 
188 //---------------------------------------------------------------------------
init()189 void FileFilter_T :: init()
190 {
191       // create 100 test objects
192    for (int i = 0; i < 100; ++i)
193       sampleData.push_back( FFTData(i) );
194 }
195 
196 
197 //---------------------------------------------------------------------------
cleanup()198 void FileFilter_T :: cleanup()
199 {
200    // empty
201 }
202 
203 
204 //---------------------------------------------------------------------------
testInitialization()205 int FileFilter_T :: testInitialization()
206 {
207    TestUtil  tester( "FileFilter", "initialization/getDataCount/size/empty", __FILE__, __LINE__ );
208 
209    try
210    {
211       FileFilter<FFTData>  ff;
212       tester.assert( true, "error creating FileFilter", __LINE__ );
213 
214       tester.assert( (0 == ff.getDataCount() ), "data count should be 0", __LINE__ );
215 
216       tester.assert( (0 == ff.size() ), "data size should be 0", __LINE__ );
217 
218       tester.assert( ff.empty(), "data list should be empty", __LINE__ );
219    }
220    catch (...)
221    {
222       tester.assert( false, "error creating FileFilter", __LINE__ );
223    }
224 
225    return tester.countFails();
226 }
227 
228 
229 //---------------------------------------------------------------------------
testData()230 int FileFilter_T :: testData()
231 {
232    TestUtil  tester( "FileFilter", "addData/getData/getDataCount/size/empty/clear", __FILE__, __LINE__ );
233 
234    try   // empty data list
235    {
236       FileFilter<FFTData>  ff;
237       FFTDataList  list;
238       ff.addData(list);
239       tester.assert( true, "error adding data", __LINE__ );
240 
241       tester.assert( (0 == ff.getDataCount() ), "data count should be 0", __LINE__ );
242 
243       tester.assert( (0 == ff.size() ), "data size should be 0", __LINE__ );
244 
245       tester.assert( ff.empty(), "data list should be empty", __LINE__ );
246 
247       FFTDataList  got = ff.getData();
248       tester.assert( true, "error getting data", __LINE__ );
249 
250       tester.assert( (0 == got.size() ), "got data size should be 0", __LINE__ );
251 
252       ff.clear();
253       tester.assert( true, "error clearing data", __LINE__ );
254 
255       tester.assert( (0 == ff.getDataCount() ), "cleared data count should be 0", __LINE__ );
256 
257       tester.assert( (0 == ff.size() ), "cleared data size should be 0", __LINE__ );
258 
259       tester.assert( ff.empty(), "cleared data list should be empty", __LINE__ );
260    }
261    catch (...)
262    {
263       tester.assert( false, "error adding data", __LINE__ );
264    }
265 
266    try   // single-item data list
267    {
268       FileFilter<FFTData>  ff;
269       FFTDataList  list;
270       list.push_back( FFTData(1) );
271       ff.addData(list);
272       tester.assert( true, "error adding data", __LINE__ );
273 
274       tester.assert( (1 == ff.getDataCount() ), "data count should be 1", __LINE__ );
275 
276       tester.assert( (1 == ff.size() ), "data size should be 1", __LINE__ );
277 
278       tester.assert( !ff.empty(), "data list should not be empty", __LINE__ );
279 
280       FFTDataList  got = ff.getData();
281       tester.assert( true, "error getting data", __LINE__ );
282 
283       tester.assert( (1 == got.size() ), "got data size should be 1", __LINE__ );
284 
285       ff.clear();
286       tester.assert( true, "error clearing data", __LINE__ );
287 
288       tester.assert( (0 == ff.getDataCount() ), "cleared data count should be 0", __LINE__ );
289 
290       tester.assert( (0 == ff.size() ), "cleared data size should be 0", __LINE__ );
291 
292       tester.assert( ff.empty(), "cleared data list should be empty", __LINE__ );
293    }
294    catch (...)
295    {
296       tester.assert( false, "error adding data", __LINE__ );
297    }
298 
299    try   // many-item data list
300    {
301       FileFilter<FFTData>  ff;
302       ff.addData( sampleData );
303       tester.assert( true, "error adding data", __LINE__ );
304 
305       ostringstream  oss;
306       oss << sampleData.size();
307 
308       tester.assert( (sampleData.size() == ff.getDataCount() ),
309                      "data count should be " + oss.str() , __LINE__ );
310 
311       tester.assert( (sampleData.size() == ff.size() ),
312                     "data size should be " + oss.str(), __LINE__ );
313 
314       tester.assert( !ff.empty(), "data list should not be empty", __LINE__ );
315 
316       FFTDataList  got = ff.getData();
317       tester.assert( true, "error getting data", __LINE__ );
318 
319       tester.assert( (sampleData.size() == got.size() ),
320                      "got data size should be " + oss.str(), __LINE__ );
321 
322       ff.clear();
323       tester.assert( true, "error clearing data", __LINE__ );
324 
325       tester.assert( (0 == ff.getDataCount() ), "cleared data count should be 0", __LINE__ );
326 
327       tester.assert( (0 == ff.size() ), "cleared data size should be 0", __LINE__ );
328 
329       tester.assert( ff.empty(), "cleared data list should be empty", __LINE__ );
330    }
331    catch (...)
332    {
333       tester.assert( false, "error adding data", __LINE__ );
334    }
335 
336    return tester.countFails();
337 }
338 
339 
340 //---------------------------------------------------------------------------
testBeginEnd()341 int FileFilter_T :: testBeginEnd()
342 {
343    TestUtil  tester( "FileFilter", "begin/end", __FILE__, __LINE__ );
344 
345    try   // empty data list
346    {
347       FileFilter<FFTData>  ff;
348 
349       FFTDataList::iterator bIter = ff.begin();
350       tester.assert( true, "iterator error", __LINE__ );
351 
352       FFTDataList::iterator eIter = ff.end();
353       tester.assert( true, "iterator error", __LINE__ );
354 
355       tester.assert( (bIter == eIter), "iterator", __LINE__ );
356    }
357    catch (...)
358    {
359       tester.assert( false, "iterator error", __LINE__ );
360    }
361 
362    try   // single-item data list
363    {
364       FileFilter<FFTData>  ff;
365       FFTDataList  list;
366       list.push_back( FFTData(1) );
367       ff.addData(list);
368 
369       FFTDataList::iterator bIter = ff.begin();
370       tester.assert( true, "iterator error", __LINE__ );
371 
372       FFTDataList::iterator eIter = ff.end();
373       tester.assert( true, "iterator error", __LINE__ );
374 
375       tester.assert( (bIter != eIter), "iterator", __LINE__ );
376 
377       bIter++;
378       tester.assert( true, "iterator error", __LINE__ );
379 
380       tester.assert( (bIter == eIter), "iterator", __LINE__ );
381    }
382    catch (...)
383    {
384       tester.assert( false, "iterator error", __LINE__ );
385    }
386 
387    try   // multiple-item data list
388    {
389       FileFilter<FFTData>  ff;
390       ff.addData( sampleData );
391 
392       FFTDataList::iterator bIter = ff.begin();
393       tester.assert( true, "iterator error", __LINE__ );
394 
395       FFTDataList::iterator eIter = ff.end();
396       tester.assert( true, "iterator error", __LINE__ );
397 
398       tester.assert( (bIter != eIter), "iterator error", __LINE__ );
399 
400       int advances = 0;
401       FFTDataList::const_iterator  sampleIter = sampleData.begin();
402       while ( (bIter != eIter) && (sampleIter != sampleData.end() ) )
403       {
404          if ( bIter->value != sampleIter->value )
405          {
406             tester.assert( false, "iterator error - value mismatch", __LINE__ );
407             break;
408          }
409          bIter++;
410          sampleIter++;
411          advances++;
412       }
413       tester.assert( (advances == sampleData.size() ), "iterator error - premature end", __LINE__ );
414 
415       tester.assert( (bIter == eIter), "iterator error - end not reached", __LINE__ );
416    }
417    catch (...)
418    {
419       tester.assert( false, "iterator error", __LINE__ );
420    }
421 
422    return tester.countFails();
423 }
424 
425 
426 //---------------------------------------------------------------------------
testFrontBack()427 int FileFilter_T :: testFrontBack()
428 {
429    TestUtil  tester( "FileFilter", "front/back", __FILE__, __LINE__ );
430 
431    try   // empty data list - front()
432    {
433       FileFilter<FFTData>  ff;
434 
435       FFTData&  data = ff.front();
436       tester.assert( false, "expected exception for empty list", __LINE__ );
437    }
438    catch (...)
439    {
440       tester.assert( true, "expected exception for empty list", __LINE__ );
441    }
442 
443    try   // empty data list - back()
444    {
445       FileFilter<FFTData>  ff;
446 
447       FFTData&  data = ff.back();
448       tester.assert( false, "expected exception for empty list", __LINE__ );
449    }
450    catch (...)
451    {
452       tester.assert( true, "expected exception for empty list", __LINE__ );
453    }
454 
455    try   // single-item data list
456    {
457       FileFilter<FFTData>  ff;
458       FFTDataList  list;
459       list.push_back( FFTData(1) );
460       ff.addData(list);
461 
462       FFTData&  fdata = ff.front();
463       tester.assert( (fdata.value == 1), "error accessing list front", __LINE__ );
464 
465       FFTData&  bdata = ff.back();
466       tester.assert( (bdata.value == 1), "error accessing list back", __LINE__ );
467    }
468    catch (...)
469    {
470       tester.assert( false, "error accessing list front/back", __LINE__ );
471    }
472 
473    try   // multiple-item data list
474    {
475       FileFilter<FFTData>  ff;
476       ff.addData( sampleData );
477 
478       FFTData&  fdata = ff.front();
479       tester.assert( (fdata.value == sampleData.front().value),
480                      "error accessing list front", __LINE__ );
481 
482       FFTData&  bdata = ff.back();
483       tester.assert( (bdata.value == sampleData.back().value),
484                      "error accessing list back", __LINE__ );
485    }
486    catch (...)
487    {
488       tester.assert( false, "error accessing list front/back", __LINE__ );
489    }
490 
491    return tester.countFails();
492 }
493 
494 
495 //---------------------------------------------------------------------------
testFilter()496 int FileFilter_T :: testFilter()
497 {
498    TestUtil  tester( "FileFilter", "filter/getFiltered", __FILE__, __LINE__ );
499 
500    try   // empty data list
501    {
502       FileFilter<FFTData>  ff;
503 
504       tester.assert( (0 == ff.getFiltered() ),
505                      "no filtering has occurred", __LINE__ );
506 
507       tester.assert( (0 == ff.filter(IsEven()).getFiltered() ),
508                      "empty list expected after filtering", __LINE__ );
509    }
510    catch (...)
511    {
512       tester.assert( false, "exception filtering empty list", __LINE__ );
513    }
514 
515    try   // single-item data list filtered to empty
516    {
517       FileFilter<FFTData>  ff;
518       FFTDataList  list;
519       list.push_back( FFTData(2) );
520       ff.addData(list);
521 
522       tester.assert( (0 == ff.getFiltered() ),
523                      "no filtering has occurred", __LINE__ );
524 
525       tester.assert( (1 == ff.filter(IsEven() ).getFiltered() ),
526                      "expected filtering", __LINE__ );
527 
528       tester.assert( (0 == ff.getDataCount() ),
529                      "empty list expected following filtering", __LINE__ );
530    }
531    catch (...)
532    {
533       tester.assert( false, "exception filtering non-empty list", __LINE__ );
534    }
535 
536    try   // single-item data list filtered to no effect
537    {
538       FileFilter<FFTData>  ff;
539       FFTDataList  list;
540       list.push_back( FFTData(3) );
541       ff.addData(list);
542 
543       tester.assert( (0 == ff.getFiltered() ),
544                      "no filtering has occurred", __LINE__ );
545 
546       tester.assert( (0 == ff.filter(IsEven()).getFiltered() ),
547                      "expected no filtering", __LINE__ );
548 
549       tester.assert( (1 == ff.getDataCount() ),
550                      "non-empty list expected following filtering", __LINE__ );
551    }
552    catch (...)
553    {
554       tester.assert( false, "exception filtering non-empty list", __LINE__ );
555    }
556 
557    try   // multiple-item data list filtering
558    {
559       FileFilter<FFTData>  ff;
560       ff.addData( sampleData );  // assumes 100 elements
561 
562       tester.assert( (0 == ff.getFiltered() ),
563                      "no filtering has occurred", __LINE__ );
564 
565       tester.assert( (50 == ff.filter(IsEven()).getFiltered() ),
566                      "expected filtering", __LINE__ );
567 
568       tester.assert( (50 == ff.getDataCount() ),
569                      "non-empty list expected following filtering", __LINE__ );
570    }
571    catch (...)
572    {
573       tester.assert( false, "error accessing list front/back", __LINE__ );
574    }
575 
576    return tester.countFails();
577 }
578 
579 
580 //---------------------------------------------------------------------------
testSort()581 int FileFilter_T :: testSort()
582 {
583    TestUtil  tester( "FileFilter", "sort", __FILE__, __LINE__ );
584 
585    try   // empty data list
586    {
587       FileFilter<FFTData>  ff;
588 
589       tester.assert( (0 == ff.sort(LessThan() ).getDataCount() ),
590                      "empty list expected after sorting", __LINE__ );
591    }
592    catch (...)
593    {
594       tester.assert( false, "exception sorting empty list", __LINE__ );
595    }
596 
597    try   // single-item data list
598    {
599       FileFilter<FFTData>  ff;
600       FFTDataList  list;
601       list.push_back( FFTData(2) );
602       ff.addData(list);
603 
604       tester.assert( (1 == ff.sort(LessThan() ).getDataCount() ),
605                      "one item expected after sorting", __LINE__ );
606 
607       tester.assert( (2 == ff.front().value), "unexpected value", __LINE__ );
608    }
609    catch (...)
610    {
611       tester.assert( false, "exception sorting non-empty list", __LINE__ );
612    }
613 
614    try   // two-item, out-of-order data list
615    {
616       FileFilter<FFTData>  ff;
617       FFTDataList  list;
618       list.push_back( FFTData(2) );
619       list.push_back( FFTData(1) );
620       ff.addData(list);
621 
622       tester.assert( (2 == ff.sort(LessThan() ).getDataCount() ),
623                      "two items expected after sorting", __LINE__ );
624 
625       tester.assert( (1 == ff.front().value), "unexpected value", __LINE__ );
626       tester.assert( (2 == ff.back().value), "unexpected value", __LINE__ );
627    }
628    catch (...)
629    {
630       tester.assert( false, "exception sorting non-empty list", __LINE__ );
631    }
632 
633    try   // multiple-item, pre-sorted data list
634    {
635       FileFilter<FFTData>  ff;
636       ff.addData( sampleData );  // assumes 100 elements
637 
638       tester.assert( (100 == ff.sort(LessThan() ).getDataCount() ),
639                      "100 items expected after sorting", __LINE__ );
640 
641       bool  sorted = true;
642       int  previous = 0;
643       FFTDataList::const_iterator  ffIter = ff.begin();
644       for ( ; ffIter != ff.end(); ++ffIter)
645       {
646          if ( (ffIter != ff.begin()) && (ffIter->value < previous) )
647          {
648             sorted = false;
649             break;
650          }
651          previous = ffIter->value;
652       }
653       tester.assert( sorted, "data list was not sorted", __LINE__ );
654 
655    }
656    catch (...)
657    {
658       tester.assert( false, "error accessing list front/back", __LINE__ );
659    }
660 
661    try   // multiple-item, un-sorted data list
662    {
663       FileFilter<FFTData>  ff;
664       FFTDataList  reversedData( sampleData );
665       reverse(reversedData.begin(), reversedData.end() );
666       ff.addData( reversedData );  // assumes 100 elements
667 
668       tester.assert( (100 == ff.sort(LessThan() ).getDataCount() ),
669                      "100 items expected after sorting", __LINE__ );
670 
671       bool  sorted = true;
672       int  previous = 0;
673       FFTDataList::const_iterator  ffIter = ff.begin();
674       for ( ; ffIter != ff.end(); ++ffIter)
675       {
676          if ( (ffIter != ff.begin()) && (ffIter->value < previous) )
677          {
678             sorted = false;
679             break;
680          }
681          previous = ffIter->value;
682       }
683       tester.assert( sorted, "data list was not sorted", __LINE__ );
684 
685    }
686    catch (...)
687    {
688       tester.assert( false, "error accessing list front/back", __LINE__ );
689    }
690 
691    return tester.countFails();
692 }
693 
694 
695 //---------------------------------------------------------------------------
testMerge()696 int FileFilter_T :: testMerge()
697 {
698    TestUtil  tester( "FileFilter", "merge", __FILE__, __LINE__ );
699 
700    try   // empty data lists
701    {
702       FileFilter<FFTData>  ff;
703       FileFilter<FFTData>  ffOther;
704 
705       tester.assert( (0 == ff.merge(ffOther).getDataCount() ),
706                      "empty list expected", __LINE__ );
707    }
708    catch (...)
709    {
710       tester.assert( false, "exception merging empty lists", __LINE__ );
711    }
712 
713    try   // empty data lists (sorted)
714    {
715       FileFilter<FFTData>  ff;
716       FileFilter<FFTData>  ffOther;
717 
718       tester.assert( (0 == ff.merge(ffOther, LessThan() ).getDataCount() ),
719                      "empty list expected", __LINE__ );
720    }
721    catch (...)
722    {
723       tester.assert( false, "exception merging empty lists", __LINE__ );
724    }
725 
726    try   // one empty data list (first)
727    {
728       FileFilter<FFTData>  ff;
729       FileFilter<FFTData>  ffOther;
730       FFTDataList  list;
731       list.push_back( FFTData(1) );
732       ffOther.addData(list);
733 
734       tester.assert( (1 == ff.merge(ffOther).getDataCount() ),
735                      "unexpected element count", __LINE__ );
736 
737       tester.assert( ( (1 == ff.getDataCount() ) && (1 == ff.front().value) ),
738                      "unexpected value", __LINE__ );
739 
740       if ( 1 != ff.getDataCount() )
741       {
742          dump(ff.getData() );
743       }
744    }
745    catch (...)
746    {
747       tester.assert( false, "exception merging lists", __LINE__ );
748    }
749 
750    try   // one empty data list (second)
751    {
752       FileFilter<FFTData>  ff;
753       FileFilter<FFTData>  ffOther;
754       FFTDataList  list;
755       list.push_back( FFTData(1) );
756       ff.addData(list);
757 
758       tester.assert( (1 == ff.merge(ffOther).getDataCount() ),
759                      "unexpected element count", __LINE__ );
760 
761       tester.assert( ( (1 == ff.getDataCount() ) && (1 == ff.front().value) ),
762                      "unexpected value", __LINE__ );
763 
764       if ( 1 != ff.getDataCount() )
765       {
766          dump(ff.getData() );
767       }
768    }
769    catch (...)
770    {
771       tester.assert( false, "exception merging lists", __LINE__ );
772    }
773 
774    try   // two non-empty data lists
775    {
776       FileFilter<FFTData>  ff;
777       FileFilter<FFTData>  ffOther;
778       FFTDataList  list;
779       list.push_back( FFTData(2) );
780       ff.addData(list);
781       list.clear();
782       list.push_back( FFTData(1) );
783       ffOther.addData(list);
784 
785       tester.assert( (2 == ff.merge(ffOther).getDataCount() ),
786                      "unexpected element count", __LINE__ );
787 
788       if ( 2 != ff.getDataCount() )
789       {
790          dump(ff.getData() );
791       }
792    }
793    catch (...)
794    {
795       tester.assert( false, "exception merging lists", __LINE__ );
796    }
797 
798    try   // two non-empty data lists (sorted)
799    {
800       FileFilter<FFTData>  ff;
801       FileFilter<FFTData>  ffOther;
802       FFTDataList  list;
803       list.push_back( FFTData(3) );
804       list.push_back( FFTData(1) );
805       ff.addData(list);
806       list.clear();
807       list.push_back( FFTData(4) );
808       list.push_back( FFTData(2) );
809       ffOther.addData(list);
810 
811       tester.assert( (4 == ff.merge(ffOther, LessThan() ).getDataCount() ),
812                      "unexpected element count", __LINE__ );
813 
814       if ( 4 == ff.getDataCount() )
815       {
816          tester.assert( (1 == ff.front().value),
817                         "unexpected value", __LINE__ );
818 
819          tester.assert( (4 == ff.back().value),
820                         "unexpected value", __LINE__ );
821       }
822       else
823       {
824          dump(ff.getData() );
825       }
826    }
827    catch (...)
828    {
829       tester.assert( false, "exception merging lists", __LINE__ );
830    }
831 
832    return tester.countFails();
833 }
834 
835 
836 //---------------------------------------------------------------------------
testTouch()837 int FileFilter_T :: testTouch()
838 {
839    TestUtil  tester( "FileFilter", "touch", __FILE__, __LINE__ );
840 
841    try   // empty data list
842    {
843       FileFilter<FFTData>  ff;
844 
845       tester.assert( (0 == ff.getFiltered() ),
846                      "no operation has occurred", __LINE__ );
847 
848       tester.assert( (0 == ff.touch(DoubleFives() ).getFiltered() ),
849                      "no operations expected", __LINE__ );
850    }
851    catch (...)
852    {
853       tester.assert( false, "exception operating on an empty list", __LINE__ );
854    }
855 
856    try   // single-item data list filtered to empty
857    {
858       FileFilter<FFTData>  ff;
859       FFTDataList  list;
860       list.push_back( FFTData(5) );
861       ff.addData(list);
862 
863       tester.assert( (0 == ff.getFiltered() ),
864                      "no operation has occurred", __LINE__ );
865 
866       tester.assert( (1 == ff.touch(DoubleFives() ).getFiltered() ),
867                      "expected a single operation", __LINE__ );
868 
869       tester.assert( (1 == ff.getDataCount() ),
870                      "unexpected change to data count", __LINE__ );
871 
872       FFTData&  fdata = ff.front();
873       tester.assert( (10 == fdata.value),
874                      "operation was not applied", __LINE__ );
875    }
876    catch (...)
877    {
878       tester.assert( false, "exception operating on a non-empty list", __LINE__ );
879    }
880 
881    try   // single-item data list filtered to no effect
882    {
883       FileFilter<FFTData>  ff;
884       FFTDataList  list;
885       list.push_back( FFTData(3) );
886       ff.addData(list);
887 
888       tester.assert( (0 == ff.getFiltered() ),
889                      "no operation has occurred", __LINE__ );
890 
891       tester.assert( (0 == ff.touch(DoubleFives() ).getFiltered() ),
892                      "no operations expected", __LINE__ );
893 
894       tester.assert( (1 == ff.getDataCount() ),
895                      "unexpected change to data count", __LINE__ );
896 
897       FFTData&  fdata = ff.front();
898       tester.assert( (3 == fdata.value),
899                      "operation was erroneously applied", __LINE__ );
900    }
901    catch (...)
902    {
903       tester.assert( false, "exception operating on a non-empty list", __LINE__ );
904    }
905 
906    try   // multiple-item data list filtering
907    {
908       FileFilter<FFTData>  ff;
909       ff.addData( sampleData );  // assumes 100 elements
910 
911       tester.assert( (0 == ff.getFiltered() ),
912                      "no operation has occurred", __LINE__ );
913 
914       tester.assert( (20 == ff.touch(DoubleFives() ).getFiltered() ),
915                      "expected 50 operations", __LINE__ );
916 
917       tester.assert( (100 == ff.getDataCount() ),
918                      "unexpected change to data count", __LINE__ );
919 
920          // check that the operation was applied to all appropriate elememts,
921          // i.e. make sure every 5th element is divisible by 10
922       bool  applied = true;
923       int i = 0;
924       FFTDataList::const_iterator  ffIter = ff.begin();
925       for ( ; ffIter != ff.end(); ++i, ++ffIter)
926       {
927          if ( (0 == (i % 5) ) && (0 != (ffIter->value % 10) ) )
928          {
929             applied = false;
930             break;
931          }
932       }
933       tester.assert( applied, "operation was not applied to all approriate elments", __LINE__ );
934    }
935    catch (...)
936    {
937       tester.assert( false, "exception operating on a non-empty list", __LINE__ );
938    }
939 
940    return tester.countFails();
941 }
942 
943 
944 //---------------------------------------------------------------------------
testUnique()945 int FileFilter_T :: testUnique()
946 {
947    TestUtil  tester( "FileFilter", "unique", __FILE__, __LINE__ );
948 
949    // @note - unique() requires a sorted list as input
950 
951    try   // empty data list
952    {
953       FileFilter<FFTData>  ff;
954 
955       tester.assert( (0 == ff.unique(Equal() ).getDataCount() ),
956                      "empty list expected", __LINE__ );
957    }
958    catch (...)
959    {
960       tester.assert( false, "exception for empty list", __LINE__ );
961    }
962 
963    try   // single-item data list
964    {
965       FileFilter<FFTData>  ff;
966       FFTDataList  list;
967       list.push_back( FFTData(2) );
968       ff.addData(list);
969 
970       tester.assert( (1 == ff.unique(Equal() ).getDataCount() ),
971                      "one item expected", __LINE__ );
972 
973       tester.assert( (2 == ff.front().value), "unexpected value", __LINE__ );
974    }
975    catch (...)
976    {
977       tester.assert( false, "exception for non-empty list", __LINE__ );
978    }
979 
980    try   // two-item data list
981    {
982       FileFilter<FFTData>  ff;
983       FFTDataList  list;
984       list.push_back( FFTData(2) );
985       list.push_back( FFTData(2) );
986       ff.addData(list);
987 
988       tester.assert( (1 == ff.unique(Equal() ).getDataCount() ),
989                      "one item expected", __LINE__ );
990 
991       tester.assert( (2 == ff.front().value), "unexpected value", __LINE__ );
992    }
993    catch (...)
994    {
995       tester.assert( false, "exception for non-empty list", __LINE__ );
996    }
997 
998    try   // multiple-item data list
999    {
1000       FileFilter<FFTData>  ff;
1001       FFTDataList  list;
1002       list.push_back( FFTData(1) );
1003       list.push_back( FFTData(2) );
1004       list.push_back( FFTData(2) );
1005       list.push_back( FFTData(2) );
1006       list.push_back( FFTData(3) );
1007       ff.addData(list);
1008 
1009       tester.assert( (3 == ff.unique(Equal() ).getDataCount() ),
1010                      "three items expected", __LINE__ );
1011 
1012       tester.assert( (1 == ff.front().value), "unexpected value", __LINE__ );
1013       tester.assert( (3 == ff.back().value), "unexpected value", __LINE__ );
1014    }
1015    catch (...)
1016    {
1017       tester.assert( false, "exception for non-empty list", __LINE__ );
1018    }
1019 
1020    return tester.countFails();
1021 }
1022 
1023 
1024 //---------------------------------------------------------------------------
testDiff()1025 int FileFilter_T :: testDiff()
1026 {
1027    TestUtil  tester( "FileFilter", "diff", __FILE__, __LINE__ );
1028 
1029    try   // empty data lists
1030    {
1031       FileFilter<FFTData>  ff;
1032       FileFilter<FFTData>  ffOther;
1033 
1034       std::pair< FFTDataList, FFTDataList >  results = ff.diff(ffOther, LessThan() );
1035 
1036       tester.assert( ( (0 == results.first.size() ) && (0 == results.second.size() ) ),
1037                      "empty lists expected", __LINE__ );
1038    }
1039    catch (...)
1040    {
1041       tester.assert( false, "exception diffing empty lists", __LINE__ );
1042    }
1043 
1044    try   // one empty data list (first)
1045    {
1046       FileFilter<FFTData>  ff;
1047       FileFilter<FFTData>  ffOther;
1048       FFTDataList  list;
1049       list.push_back( FFTData(1) );
1050       ffOther.addData(list);
1051 
1052       std::pair< FFTDataList, FFTDataList >  results = ff.diff(ffOther, LessThan() );
1053 
1054       tester.assert( ( (0 == results.first.size() ) && (1 == results.second.size() ) ),
1055                      "unexpected element count(s)", __LINE__ );
1056 
1057       tester.assert( ( (1 == results.second.size() ) && (1 == results.second.front().value) ),
1058                      "unexpected value", __LINE__ );
1059    }
1060    catch (...)
1061    {
1062       tester.assert( false, "exception diffing lists", __LINE__ );
1063    }
1064 
1065    try   // one empty data list (second)
1066    {
1067       FileFilter<FFTData>  ff;
1068       FileFilter<FFTData>  ffOther;
1069       FFTDataList  list;
1070       list.push_back( FFTData(1) );
1071       ff.addData(list);
1072 
1073       std::pair< FFTDataList, FFTDataList >  results = ff.diff(ffOther, LessThan() );
1074 
1075       tester.assert( ( (1 == results.first.size() ) && (0 == results.second.size() ) ),
1076                      "unexpected element count(s)", __LINE__ );
1077 
1078       tester.assert( ( (1 == results.first.size() ) && (1 == results.first.front().value) ),
1079                      "unexpected value", __LINE__ );
1080    }
1081    catch (...)
1082    {
1083       tester.assert( false, "exception diffing lists", __LINE__ );
1084    }
1085 
1086    try   // two identical non-empty data lists
1087    {
1088       FileFilter<FFTData>  ff;
1089       FileFilter<FFTData>  ffOther;
1090       FFTDataList  list;
1091       list.push_back( FFTData(1) );
1092       ff.addData(list);
1093       ffOther.addData(list);
1094 
1095       std::pair< FFTDataList, FFTDataList >  results = ff.diff(ffOther, LessThan() );
1096 
1097       tester.assert( ( (0 == results.first.size() ) && (0 == results.second.size() ) ),
1098                      "empty lists expected", __LINE__ );
1099 
1100       if ( (0 != results.first.size() ) || (0 != results.second.size() ) )
1101       {
1102          dump(results.first);
1103          dump(results.second);
1104       }
1105    }
1106    catch (...)
1107    {
1108       tester.assert( false, "exception diffing lists", __LINE__ );
1109    }
1110 
1111    try   // two non-identical non-empty data lists
1112    {
1113       FileFilter<FFTData>  ff;
1114       FileFilter<FFTData>  ffOther;
1115       FFTDataList  list;
1116       list.push_back( FFTData(1) );
1117       ff.addData(list);
1118       list.clear();
1119       list.push_back( FFTData(2) );
1120       ffOther.addData(list);
1121 
1122       std::pair< FFTDataList, FFTDataList >  results = ff.diff(ffOther, LessThan() );
1123 
1124       tester.assert( ( (1 == results.first.size() ) && (1 == results.second.size() ) ),
1125                      "expected element count(s)", __LINE__ );
1126 
1127       tester.assert( ( (1 == results.first.size() ) && (1 == results.first.front().value) ),
1128                      "unexpected value", __LINE__ );
1129 
1130       tester.assert( ( (1 == results.second.size() ) && (2 == results.second.front().value) ),
1131                      "unexpected value", __LINE__ );
1132 
1133       if ( (1 != results.first.size() ) || (1 != results.second.size() ) )
1134       {
1135          dump(results.first);
1136          dump(results.second);
1137       }
1138    }
1139    catch (...)
1140    {
1141       tester.assert( false, "exception diffing lists", __LINE__ );
1142    }
1143 
1144    return tester.countFails();
1145 }
1146 
1147 
1148 //---------------------------------------------------------------------------
testFindAll()1149 int FileFilter_T :: testFindAll()
1150 {
1151    TestUtil  tester( "FileFilter", "findAll", __FILE__, __LINE__ );
1152 
1153    try   // empty data list
1154    {
1155       FileFilter<FFTData>  ff;
1156 
1157       FFTDataList  fftdList = ff.findAll(IsEven() );
1158       tester.assert( (0 == fftdList.size() ),
1159                      "empty list expected", __LINE__ );
1160    }
1161    catch (...)
1162    {
1163       tester.assert( false, "exception searching empty list", __LINE__ );
1164    }
1165 
1166    try   // non-empty list, no matches
1167    {
1168       FileFilter<FFTData>  ff;
1169       ff.addData( sampleData );
1170 
1171       FFTDataList  fftdList = ff.findAll(Above999() );
1172       tester.assert( (0 == fftdList.size() ),
1173                      "empty list expected", __LINE__ );
1174 
1175    }
1176    catch (...)
1177    {
1178       tester.assert( false, "exception searching non-empty list", __LINE__ );
1179    }
1180 
1181    try   // non-empty list, several matches
1182    {
1183       FileFilter<FFTData>  ff;
1184       ff.addData( sampleData );
1185 
1186       FFTDataList  fftdList = ff.findAll(IsEven() );
1187       tester.assert( (50 == fftdList.size() ),
1188                      "50 element list expected", __LINE__ );
1189    }
1190    catch (...)
1191    {
1192       tester.assert( false, "exception searching non-empty list", __LINE__ );
1193    }
1194 
1195    return tester.countFails();
1196 }
1197 
1198 
1199 //---------------------------------------------------------------------------
dump(const FFTDataList & data)1200 void FileFilter_T :: dump(const FFTDataList& data)
1201 {
1202    cout << "  DATA DUMP:" << endl;
1203    FFTDataList::const_iterator  iter = data.begin();
1204    for ( ; iter != data.end(); ++iter)
1205       cout << "    " << iter->value << endl;
1206 }
1207 
1208 
1209  /** Initialize and run all tests.
1210   *
1211   * @return Total error count for all tests
1212   */
main(int argc,char * argv[])1213 int main(int argc, char *argv[])
1214 {
1215    int  errorTotal = 0;
1216 
1217    FileFilter_T  testClass;
1218 
1219    errorTotal += testClass.testInitialization();
1220    errorTotal += testClass.testData();
1221    errorTotal += testClass.testBeginEnd();
1222    errorTotal += testClass.testFrontBack();
1223    errorTotal += testClass.testFilter();
1224    errorTotal += testClass.testSort();
1225    errorTotal += testClass.testMerge();
1226    errorTotal += testClass.testTouch();
1227    errorTotal += testClass.testUnique();
1228    errorTotal += testClass.testDiff();
1229    errorTotal += testClass.testFindAll();
1230 
1231    cout << "Total Failures for " << __FILE__ << ": " << errorTotal << endl;
1232 
1233    return errorTotal;
1234 }
1235