feisty meow concerns codebase  2.140
test_matrix.cpp
Go to the documentation of this file.
1 /*
2 * Name : test_matrix
3 * Author : Chris Koeritz
4 **
5 * Copyright (c) 1992-$now By Author. This program is free software; you can *
6 * redistribute it and/or modify it under the terms of the GNU General Public *
7 * License as published by the Free Software Foundation; either version 2 of *
8 * the License or (at your option) any later version. This is online at: *
9 * http://www.fsf.org/copyleft/gpl.html *
10 * Please send any updates to: fred@gruntose.com *
11 */
12 
14 #include <basis/astring.h>
15 #include <basis/guards.h>
16 #include <loggers/console_logger.h>
17 #include <structures/matrix.h>
19 #include <unit_test/unit_base.h>
20 
21 using namespace application;
22 using namespace basis;
23 using namespace mathematics;
24 using namespace filesystem;
25 using namespace loggers;
26 using namespace structures;
27 using namespace textual;
28 using namespace timely;
29 using namespace unit_test;
30 
31 //#define DEBUG_MATRIX
32  // uncomment for noisier version.
33 
34 const int DIM_ROWS = 10;
35 const int DIM_COLS = 10;
36 
37 // fills the matrix "to_stuff" with the pure version of the exemplar.
38 #define STUFF_MATRIX(to_stuff, max_row, max_col) \
39  to_stuff.reset(max_row, max_col); \
40  for (int r = 0; r < max_row; r++) \
41  for (int c = 0; c < max_col; c++) \
42  to_stuff.put(r, c, test_pure.get(r, c))
43 
45 
46 // forward.
47 class my_int_matrix;
48 
50 
51 // this class exhibits an old bug where the matrix was zeroing out its
52 // contents for a same size resize. the zeroing allowed hell to spew forth.
53 class diggulite
54 {
55 public:
56  diggulite() {}
57  virtual ~diggulite() {}
58 };
59 
61 
62 class test_matrix : virtual public unit_base, virtual public application_shell
63 {
64 public:
65  test_matrix();
66 
67  DEFINE_CLASS_NAME("test_matrix");
68 
69  void log(const astring &to_print) { application_shell::log(to_print); }
70  // override to avoid redoing all the logs here.
71 
72  int execute();
73  // performs main body of test.
74 
75  static astring dump_matrix(const my_int_matrix &to_print);
76  // creates a nice form of the matrix "to_print".
77 
78  void print_matrix(const my_int_matrix &to_print);
79  // dumps "to_print" to the diagnostic output.
80 
81  void test_out_submatrix(const my_int_matrix &source);
83 
84  void test_out_redimension();
86 
87  void test_out_resizing_virtual_objects();
89 
90  void test_out_zapping(const my_int_matrix &test_pure);
92 
93  void test_out_inserting(const my_int_matrix &test_pure);
95 };
96 
98 
99 class my_int_matrix : public int_matrix, virtual public hoople_standard
100 {
101 public:
102  my_int_matrix(int r = 0, int c = 0) : int_matrix(r, c) {}
103  my_int_matrix(const int_matrix &init) : int_matrix(init) {}
104 
105  DEFINE_CLASS_NAME("my_int_matrix");
106 
107  virtual bool equal_to(const equalizable &s2) const {
108  const my_int_matrix *sec = dynamic_cast<const my_int_matrix *>(&s2);
109  if (!sec) return false;
110  if (rows() != sec->rows()) return false;
111  if (columns() != sec->columns()) return false;
112  for (int r = 0; r < this->rows(); r++)
113  for (int c = 0; c < this->columns(); c++)
114  if ((*this)[r][c] != (*sec)[r][c]) return false;
115  return true;
116  }
117 
118  virtual void text_form(base_string &state_fill) const {
119  state_fill.assign(test_matrix::dump_matrix(*this));
120  }
121 };
122 
124 
125 test_matrix::test_matrix() : application_shell() {}
126 
127 astring test_matrix::dump_matrix(const my_int_matrix &to_print)
128 {
129  astring text;
130  for (int t = 0; t < to_print.rows(); t++) {
131  text += astring(astring::SPRINTF, "[%d] ", t);
132  for (int c = 0; c < to_print.columns(); c++)
133  text += astring(astring::SPRINTF, "%03d ", int(to_print[t][c]));
134  text += parser_bits::platform_eol_to_chars();
135  }
136  return text;
137 }
138 
139 void test_matrix::print_matrix(const my_int_matrix &to_print)
140 { log(astring("\n") + dump_matrix(to_print)); }
141 
142 void test_matrix::test_out_submatrix(const my_int_matrix &source)
143 {
144  FUNCDEF("test_out_submatrix")
145  my_int_matrix test2(source);
146 
147  for (int s = 0; s < DIM_ROWS; s++)
148  for (int c = 0; c < DIM_COLS; c++)
149  ASSERT_EQUAL(source[s][c], test2[s][c], "computed matrices should be same after copy");
150 
151 #ifdef DEBUG_MATRIX
152  log("before submatrix:");
153  print_matrix(test2);
154 #endif
155  my_int_matrix chunk(test2.submatrix(2, 3, 3, 2));
156  my_int_matrix chunk_comparator(3, 2);
157  for (int r = 0; r < 3; r++)
158  for (int c = 0; c < 2; c++)
159  chunk_comparator[r][c] = test2[r+2][c+3];
160  ASSERT_EQUAL(chunk, chunk_comparator, "submatrix should grab proper contents");
161 #ifdef DEBUG_MATRIX
162  log("after submatrix, chunk of the matrix has:");
163  print_matrix(chunk);
164 #endif
165 }
166 
167 void test_matrix::test_out_redimension()
168 {
169  FUNCDEF("test_out_redimension")
170  my_int_matrix computed(7, 14);
171  for (int x1 = 0; x1 < 7; x1++) {
172  for (int y1 = 0; y1 < 14; y1++) {
173  if ( (x1 * y1) % 2) computed[x1][y1] = 1 + x1 * 100 + y1;
174  else computed.put(x1, y1, 1 + x1 * 100 + y1);
175  }
176  }
177 
178  for (int x2 = 6; x2 >= 0; x2--) {
179  for (int y2 = 13; y2 >= 0; y2--) {
180  ASSERT_EQUAL(computed[x2][y2], 1 + x2 * 100 + y2,
181  "computed matrix should have proper computed values");
182  }
183  }
184 
185  computed.redimension(3, 5);
186  ASSERT_FALSE( (computed.rows() != 3) || (computed.columns() != 5),
187  "redimension should not get size wrong");
188  for (int x3 = 2; x3 >= 0; x3--) {
189  for (int y3 = 4; y3 >= 0; y3--) {
190  ASSERT_EQUAL(computed[x3][y3], 1 + x3 * 100 + y3,
191  "computed matrix should still have right values");
192  }
193  }
194 
195  computed.redimension(0, 0);
196  ASSERT_FALSE(computed.rows() || computed.columns(),
197  "redimension to zero should see matrix as empty");
198 
199  computed.reset(12, 20);
200  ASSERT_FALSE( (computed.rows() != 12) || (computed.columns() != 20),
201  "resize should compute proper size");
202 }
203 
204 void test_matrix::test_out_resizing_virtual_objects()
205 {
206  FUNCDEF("test_out_resizing_virtual_objects")
207  // this test block ensures that the matrix doesn't blow up from certain
208  // resizing operations performed on a templated type that has a virtual
209  // destructor.
210  matrix<diggulite> grids;
211  grids.reset();
212  grids.redimension ( 0, 1 );
213  grids.redimension ( 1, 1 );
214  grids.reset(1, 1);
215  ASSERT_TRUE(true, "no explosions should occur due to virtual contents");
216 }
217 
218 void test_matrix::test_out_zapping(const my_int_matrix &test_pure)
219 {
220  FUNCDEF("test_out_zapping")
221  // this block tests the zapping ops.
222  my_int_matrix test_zap;
223  STUFF_MATRIX(test_zap, DIM_ROWS, DIM_COLS);
224 
225 #ifdef DEBUG_MATRIX
226  log("matrix before zappage:");
227  print_matrix(test_zap);
228 #endif
229 
230  my_int_matrix compare_1 = test_zap;
231  ASSERT_EQUAL(compare_1, test_zap, "assignment works right");
232  test_zap.zap_row(5);
233  // make same changes but with different ops so we can compare.
234  for (int r = 6; r < DIM_ROWS; r++)
235  for (int c = 0; c < DIM_COLS; c++)
236  compare_1[r - 1][c] = compare_1[r][c];
237  compare_1.zap_row(DIM_ROWS - 1); // lose the last row now.
238  ASSERT_EQUAL(compare_1, test_zap, "zapping should work regardless of path");
239 
240 #ifdef DEBUG_MATRIX
241  log("matrix after zappage of row 5:");
242  print_matrix(test_zap);
243 #endif
244 
245  // reset the array again.
246  STUFF_MATRIX(test_zap, DIM_ROWS, DIM_COLS);
247  my_int_matrix compare_2 = test_zap;
248  test_zap.zap_column(3);
249  // now make those same changes in our compare array.
250  for (int r = 0; r < DIM_ROWS; r++)
251  for (int c = 4; c < DIM_COLS; c++)
252  compare_2[r][c - 1] = compare_2[r][c];
253  compare_2.zap_column(DIM_COLS - 1); // lose the last row now.
254  ASSERT_EQUAL(compare_2, test_zap, "second zapping should work regardless of path");
255 
256 #ifdef DEBUG_MATRIX
257  log("matrix after zappage of column 3:");
258  print_matrix(test_zap);
259 #endif
260 
261  // reset test_zap again.
262  STUFF_MATRIX(test_zap, DIM_ROWS, DIM_COLS);
263  my_int_matrix compare_3(test_zap.submatrix(1, 1, DIM_ROWS - 2, DIM_COLS - 2));
264  test_zap.zap_column(0);
265  test_zap.zap_row(0);
266  test_zap.zap_row(test_zap.rows() - 1);
267  test_zap.zap_column(test_zap.columns() - 1);
268  ASSERT_EQUAL(test_zap, compare_3, "zapping and submatrix should compute same result");
269 
270 #ifdef DEBUG_MATRIX
271  log("matrix after zap of row 0, col 0, last row, last col");
272  print_matrix(test_zap);
273 #endif
274 }
275 
276 void test_matrix::test_out_inserting(const my_int_matrix &test_pure)
277 {
278  FUNCDEF("test_out_inserting")
279  // this block tests the inserting ops.
280  my_int_matrix test_insert;
281  STUFF_MATRIX(test_insert, 4, 4);
282 
283 #ifdef DEBUG_MATRIX
284  log("matrix before inserting:");
285  print_matrix(test_insert);
286 #endif
287 
288  my_int_matrix compare_1(test_insert);
289  test_insert.insert_row(2);
290  compare_1.insert_row(4);
291  for (int r = 3; r >= 2; r--)
292  for (int c = 0; c < 4; c++)
293  compare_1[r + 1][c] = compare_1[r][c];
294  for (int c = 0; c < 4; c++)
295  compare_1[2][c] = 0;
296  ASSERT_EQUAL(test_insert, compare_1, "inserting row should create expected array");
297 
298 #ifdef DEBUG_MATRIX
299  log("matrix after insert of row 2:");
300  print_matrix(test_insert);
301 #endif
302 
303  // reset test_insert again.
304  STUFF_MATRIX(test_insert, 5, 6);
305 
306 #ifdef DEBUG_MATRIX
307  log("reset matrix before inserting:");
308  print_matrix(test_insert);
309 #endif
310 
311  my_int_matrix compare_2(test_insert);
312  test_insert.insert_column(3);
313  compare_2.insert_column(6);
314  for (int r = 0; r < 5; r++)
315  for (int c = 5; c >= 3; c--)
316  compare_2[r][c + 1] = compare_2[r][c];
317  for (int r = 0; r < 5; r++)
318  compare_2[r][3] = 0;
319  ASSERT_EQUAL(test_insert, compare_2, "inserting column should create expected array");
320 
321 #ifdef DEBUG_MATRIX
322  log("matrix after insert of column 3:");
323  print_matrix(test_insert);
324 #endif
325 
326  // reset test_insert again.
327  STUFF_MATRIX(test_insert, 3, 3);
328  my_int_matrix compare_3(5, 5);
329  for (int r = 0; r < 3; r++)
330  for (int c = 0; c < 3; c++)
331  compare_3[r + 1][c + 1] = test_insert[r][c];
332  for (int r = 0; r < 5; r++) { compare_3[r][0] = 0; compare_3[r][4] = 0; }
333  for (int c = 0; c < 5; c++) { compare_3[0][c] = 0; compare_3[4][c] = 0; }
334 
335 #ifdef DEBUG_MATRIX
336  log("matrix before inserting:");
337  print_matrix(test_insert);
338 #endif
339 
340  test_insert.insert_column(0);
341 
342 #ifdef DEBUG_MATRIX
343  log("insert col at 0");
344  print_matrix(test_insert);
345 #endif
346 
347  test_insert.insert_row(test_insert.rows());
348 
349 #ifdef DEBUG_MATRIX
350  log("insert row at rows()");
351  print_matrix(test_insert);
352 #endif
353 
354  test_insert.insert_column(test_insert.columns());
355 
356 #ifdef DEBUG_MATRIX
357  log("insert col at cols()");
358  print_matrix(test_insert);
359  log("insert row at 0...");
360 #endif
361 
362  test_insert.insert_row(0);
363 
364  ASSERT_EQUAL(test_insert, compare_3,
365  "inserting some rows and columns should create expected array");
366 
367 #ifdef DEBUG_MATRIX
368  log(astring("matrix after insert of col 0, last row, last col, row 0"));
369  print_matrix(test_insert);
370 #endif
371 }
372 
373 int test_matrix::execute()
374 {
375  FUNCDEF("execute");
376 
377  my_int_matrix test_pure(DIM_ROWS, DIM_COLS); // kept without modification.
378  for (int r = 0; r < DIM_ROWS; r++)
379  for (int c = 0; c < DIM_COLS; c++)
380  test_pure[r][c] = r * DIM_COLS + c;
381 
382  my_int_matrix test1 = test_pure; // first copy to work with.
383 
384  test1.reset();
385  ASSERT_FALSE(test1.rows() || test1.columns(), "after reset matrix should be empty");
386 
387  test_out_submatrix(test_pure);
388 
389  test_out_redimension();
390 
391  test_out_resizing_virtual_objects();
392 
393  test_out_zapping(test_pure);
394 
395  test_out_inserting(test_pure);
396 
397  return final_report();
398 }
399 
400 HOOPLE_MAIN(test_matrix, )
401 
The application_shell is a base object for console programs.
virtual basis::outcome log(const basis::base_string &to_print, int filter=basis::ALWAYS_PRINT)
< returns the full name of the current application.
Provides a dynamically resizable ASCII character string.
Definition: astring.h:35
Defines the base class for all string processing objects in hoople.
Definition: base_string.h:28
virtual base_string & assign(const base_string &s)=0
Sets the contents of this string to "s".
Base class for object that can tell itself apart from other instances.
Definition: contracts.h:44
the base class of the most easily used and tested objects in the library.
Definition: contracts.h:161
A matrix of integers.
Definition: matrix.h:112
Represents a two-dimensional array of objects.
Definition: matrix.h:32
char * copy(register char *str)
Definition: makedep.cpp:554
#define DEFINE_CLASS_NAME(objname)
Defines the name of a class by providing a couple standard methods.
Definition: enhance_cpp.h:45
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition: enhance_cpp.h:57
Provides macros that implement the 'main' program of an application.
#define HOOPLE_MAIN(obj_name, obj_args)
options that should work for most unix and linux apps.
Definition: hoople_main.h:61
Implements an application lock to ensure only one is running at once.
The guards collection helps in testing preconditions and reporting errors.
Definition: array.h:30
A platform independent way to obtain the timestamp of a file.
Definition: byte_filer.cpp:37
A logger that sends to the console screen using the standard output device.
An extension to floating point primitives providing approximate equality.
Definition: averager.h:21
A dynamic container class that holds any kind of object via pointers.
Definition: amorph.h:55
#include <time.h>
Definition: earth_time.cpp:37
Useful support functions for unit testing, especially within hoople.
Definition: unit_base.cpp:35
const int DIM_COLS
Definition: test_matrix.cpp:35
const int DIM_ROWS
Definition: test_matrix.cpp:34
#define STUFF_MATRIX(to_stuff, max_row, max_col)
Definition: test_matrix.cpp:38
#define ASSERT_EQUAL(a, b, test_name)
Definition: unit_base.h:38
#define ASSERT_TRUE(a, test_name)
Definition: unit_base.h:46
#define ASSERT_FALSE(a, test_name)
Definition: unit_base.h:50