Waveform
Waveform is a C++ header-only library which represents both the time and the frequency domains of a waveform/signal as a single object, transforming using FFTW automatically when needed.
 All Classes Namespaces Functions Typedefs Friends Groups
Waveform_test.cpp
1 //
2 //
3 // Set:
4 //
5 // $ export GTEST_HOME=gtest-1.7.0/
6 // $ export LD_LIBRARY_PATH=$GTEST_HOME/lib:$LD_LIBRARYPATH
7 //
8 // Compile with:
9 //
10 // g++ -std=c++11 -I. -I $GTEST_HOME/include -L $GTEST_HOME/lib -lgtest -lgtest_main -lpthread test_Waveform.cpp -o test_Waveform
11 //
12 //
13 //
14 
15 /*
16  To Do:
17 
18  [ ] Use Global Environment functionality for the test arrays loaded from files
19  [ ] Use type-parameterized tests so that any container can be tested without
20  needing to duplicate code
21  [ ] Use value-parameterized tests so that test arrays can be individually passed
22  to the tests for verification
23  */
24 
25 
26 #include <iostream>
27 #include <fstream>
28 #include <vector>
29 #include <complex>
30 
31 #include <Waveform.hpp>
32 #include <gtest/gtest.h>
33 
34 #include <boost/archive/text_iarchive.hpp>
35 //#include <boost/archive/text_oarchive.hpp>
36 #include <boost/serialization/vector.hpp>
37 #include <boost/serialization/complex.hpp>
38 
39 
40 // From http://stackoverflow.com/questions/1460703/comparison-of-arrays-in-google-test
42 #define EXPECT_ITERABLE_BASE( PREDICATE, REFTYPE, TARTYPE, ref, target) \
43  { \
44  const REFTYPE& ref_(ref); \
45  const TARTYPE& target_(target); \
46  REFTYPE::const_iterator refIter = ref_.begin(); \
47  TARTYPE::const_iterator tarIter = target_.begin(); \
48  unsigned int i = 0; \
49  while(refIter != ref_.end()) { \
50  if ( tarIter == target_.end() ) { \
51  ADD_FAILURE() << #target " has a smaller length than " #ref ; \
52  break; \
53  } \
54  PREDICATE(* refIter, * tarIter) \
55  << "Containers " #ref " (refIter) and " #target " (tarIter)" \
56  " differ at index " << i; \
57  ++refIter; ++tarIter; ++i; \
58  } \
59  EXPECT_TRUE( tarIter == target_.end() ) \
60  << #ref " has a smaller length than " #target ; \
61  }
62 
64 #define EXPECT_ITERABLE_EQ( TYPE, ref, target) \
65  EXPECT_ITERABLE_BASE( EXPECT_EQ, TYPE, TYPE, ref, target )
66 
68 #define EXPECT_ITERABLE_EQ2( REFTYPE, TARTYPE, ref, target) \
69  EXPECT_ITERABLE_BASE( EXPECT_EQ, REFTYPE, TARTYPE, ref, target )
70 
72 #define EXPECT_ITERABLE_DOUBLE_EQ( TYPE, ref, target) \
73  EXPECT_ITERABLE_BASE( EXPECT_DOUBLE_EQ, TYPE, TYPE, ref, target )
74 
75 
76 // Modified EXPECT_ITERABLE_BASE so that it doesn't need type specifiers
77 #define EXPECT_ITERABLE_BASE_NOTYPE( PREDICATE, ref, target) \
78  { \
79  typedef decltype(ref) REFTYPE; \
80  typedef decltype(target) TARTYPE; \
81  const REFTYPE& ref_(ref); \
82  const TARTYPE& target_(target); \
83  auto /*typename REFTYPE::const_iterator*/ refIter = ref_.begin(); \
84  auto /*typename TARTYPE::const_iterator*/ tarIter = target_.begin(); \
85  unsigned int i = 0; \
86  while(refIter != ref_.end()) { \
87  if ( tarIter == target_.end() ) { \
88  ADD_FAILURE() << #target " has a smaller length than " #ref ; \
89  break; \
90  } \
91  PREDICATE(* refIter, * tarIter) \
92  << "Containers " #ref " (refIter) and " #target " (tarIter)" \
93  " differ at index " << i; \
94  ++refIter; ++tarIter; ++i; \
95  } \
96  EXPECT_TRUE( tarIter == target_.end() ) \
97  << #ref " has a smaller length than " #target ; \
98  }
99 
100 /*
101 #define EXPECT_COMPLEX_EQ(expected, actual)\
102  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<std::complex<double> >, \
103  expected, actual)
104 
105 
106 #define ASSERT_COMPLEX_EQ(expected, actual)\
107  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<std::complex<double> >, \
108  expected, actual)
109 */
110 
111 
112 #define EXPECT_ITERABLE_EQ_NOTYPE( ref, target) \
113  EXPECT_ITERABLE_BASE_NOTYPE(EXPECT_EQ, ref, target )
114 
115 #define EXPECT_ITERABLE_FLOAT_EQ_NOTYPE( ref, target) \
116  EXPECT_ITERABLE_BASE_NOTYPE(EXPECT_FLOAT_EQ, ref, target )
117 #define EXPECT_ITERABLE_DOUBLE_EQ_NOTYPE( ref, target) \
118  EXPECT_ITERABLE_BASE_NOTYPE(EXPECT_DOUBLE_EQ, ref, target )
119 /*
120 #define EXPECT_ITERABLE_COMPLEX_EQ_NOTYPE( ref, target) \
121  EXPECT_ITERABLE_BASE_NOTYPE(EXPECT_COMPLEX_EQ, ref, target )
122 */
123 
124 using namespace PS;
125 
126 namespace {
127 
128 typedef std::vector<double> RealType;
129 typedef std::vector< std::complex<double> > ComplexType;
130 typedef Waveform<std::vector<double>, std::vector< std::complex<double> > > WaveformType;
131 
132 
133 template <typename T>
134 std::vector<T>
135 parse_dat_file (std::string fileName)
136 {
137  std::ifstream ifs(fileName.c_str());
138  assert(ifs.good());
139 
140 
141  std::vector<T> result { std::istream_iterator<T>(ifs)
142  , std::istream_iterator<T>() };
143 
144  return result;
145 }
146 
147 
148 class WaveformTest : public ::testing::Test {
149  protected:
150 
151  WaveformTest()
152  {
153 
154  }
155 
156  virtual
157  ~WaveformTest()
158  {
159 
160  }
161 
162  virtual
163  void
164  SetUp()
165  {
166  /*
167  std::ofstream ofst("bs_WaveformTest_tDomainExampleData_.txt");
168  boost::archive::text_oarchive oat (ofst);
169  oat & tDomainExampleData_;
170 
171  std::ofstream ofsf("bs_WaveformTest_fDomainExampleData_.txt");
172  boost::archive::text_oarchive oaf (ofsf);
173  oaf & fDomainExampleData_;
174  */
175 
176  std::ifstream ifs_tDomain("test_data/bs_WaveformTest_tDomain_.txt");
177  boost::archive::text_iarchive ia_tDomain(ifs_tDomain);
178  ia_tDomain >> tDomainExampleData_;
179 
180  std::ifstream ifs_fDomain("test_data/bs_WaveformTest_fDomain_.txt");
181  boost::archive::text_iarchive ia_fDomain(ifs_fDomain);
182  ia_fDomain >> fDomainExampleData_;
183 
184 
185  stepFn1024_real = parse_dat_file<double>("test_data/stepFn1024_real.dat");
186  stepFn1024_complex = parse_dat_file<std::complex<double> >("test_data/stepFn1024_complex.dat");
187 
188  diracFn1024_real = parse_dat_file<double>("test_data/diracFn1024_real.dat");
189  diracFn1024_complex = parse_dat_file<std::complex<double> >("test_data/diracFn1024_complex.dat");
190 
191  triangleFn1024_real = parse_dat_file<double>("test_data/triangleFn1024_real.dat");
192  triangleFn1024_complex = parse_dat_file<std::complex<double> >("test_data/triangleFn1024_complex.dat");
193 
194  squareFn1024_real = parse_dat_file<double>("test_data/squareFn1024_real.dat");
195  squareFn1024_complex = parse_dat_file<std::complex<double> >("test_data/squareFn1024_complex.dat");
196 
197 
198  testArrays_real.push_back(stepFn1024_real);
199  testArrays_real.push_back(diracFn1024_real);
200  testArrays_real.push_back(triangleFn1024_real);
201  testArrays_real.push_back(squareFn1024_real);
202 
203  testArrays_complex.push_back(stepFn1024_complex);
204  testArrays_complex.push_back(diracFn1024_complex);
205  testArrays_complex.push_back(triangleFn1024_complex);
206  testArrays_complex.push_back(squareFn1024_complex);
207 
208 
209  }
210 
211  virtual
212  void
213  TearDown()
214  {
215 
216  }
217 
218 
219  RealType tDomainExampleData_;
220 
221  ComplexType fDomainExampleData_;
222 
223 
224 
225  std::vector<double> stepFn1024_real;
226  std::vector< std::complex<double> > stepFn1024_complex;
227 
228  std::vector<double> diracFn1024_real;
229  std::vector< std::complex<double> > diracFn1024_complex;
230 
231  std::vector<double> triangleFn1024_real;
232  std::vector< std::complex<double> > triangleFn1024_complex;
233 
234  std::vector<double> squareFn1024_real;
235  std::vector< std::complex<double> > squareFn1024_complex;
236 
237  std::vector< std::vector<double> > testArrays_real;
238  std::vector< std::vector<std::complex<double> > > testArrays_complex;
239 
240 
241 
242  //RealType tDomain_;
243 };
244 
245 
246 
247 TEST_F(WaveformTest,FillConstructor)
248 {
249  WaveformType filltest (512);
250 
251  EXPECT_EQ(512, filltest.size());
252 
253 
254 }
255 
256 TEST_F(WaveformTest,CopyConstructor)
257 {
258  WaveformType originalWfm (tDomainExampleData_);
259 
260 
261  WaveformType copiedWfm (originalWfm);
262 
263 
264  EXPECT_ITERABLE_DOUBLE_EQ_NOTYPE(originalWfm.GetConstTimeSeries(), copiedWfm.GetConstTimeSeries());
265 
266  EXPECT_ITERABLE_EQ_NOTYPE(originalWfm.GetConstFreqSpectrum(), copiedWfm.GetConstFreqSpectrum());
267 
268  /*
269  EXPECT_EQ(copiedWfm.size(), originalWfm.size());
270 
271  for (unsigned i = 0; i < copiedWfm.size(); ++i) {
272  EXPECT_EQ(copiedWfm.GetConstTimeSeries().at(i) , originalWfm.GetConstTimeSeries().at(i));
273  }
274 
275  EXPECT_EQ(copiedWfm.size(), originalWfm.size());
276 
277  for (unsigned i = 0; i < copiedWfm.GetConstFreqSpectrum().size(); ++i) {
278  EXPECT_EQ(copiedWfm.GetConstFreqSpectrum().at(i) , originalWfm.GetConstFreqSpectrum().at(i));
279  }
280  */
281 
282 }
283 
284 TEST_F(WaveformTest,TimeDomainRangeConstructor)
285 {
286  WaveformType timedomaintest (tDomainExampleData_);
287 
288  EXPECT_ITERABLE_DOUBLE_EQ_NOTYPE(tDomainExampleData_, timedomaintest.GetConstTimeSeries());
289 }
290 
291 TEST_F(WaveformTest,FreqDomainRangeConstructor)
292 {
293  WaveformType freqdomaintest (fDomainExampleData_);
294 
295  //
296  // Approach #1
297  //
298 
299  EXPECT_EQ(fDomainExampleData_.size(), freqdomaintest.size()/2 + 1);
300 
301  for (unsigned i = 0; i < fDomainExampleData_.size(); ++i) {
302  EXPECT_EQ(fDomainExampleData_[i] , freqdomaintest.GetConstFreqSpectrum().at(i));
303  }
304 
305 
306  //
307  // Approach #2
308  //
309 
310  EXPECT_EQ(fDomainExampleData_, freqdomaintest.GetConstFreqSpectrum());
311 
312 
313  //
314  // Approach #3
315  //
316 
317  EXPECT_TRUE(fDomainExampleData_ == freqdomaintest.GetConstFreqSpectrum());
318 
319 
320  //
321  // Approach #4
322  //
323 
324  EXPECT_ITERABLE_EQ(decltype(fDomainExampleData_), fDomainExampleData_, freqdomaintest.GetConstFreqSpectrum());
325 
326 
327  //
328  // Approach #5
329  //
330 
331  EXPECT_ITERABLE_EQ_NOTYPE(fDomainExampleData_, freqdomaintest.GetConstFreqSpectrum());
332 
333 }
334 
335 TEST_F(WaveformTest,CopyAssignOperator)
336 {
337 
338  ADD_FAILURE() << "Not Yet Implemented!";
339 }
340 
341 }; // namespace
342 
343 int
344 main (int argc, char** argv)
345 {
346  ::testing::InitGoogleTest(&argc, argv);
347  return RUN_ALL_TESTS();
348 }
Waveform class: Transform as-needed between time and freq domains.
Definition: Waveform.hpp:131