AUnit  0.5.2
Unit testing framework for Arduino platforms inspired by ArduinoUnit and Google Test.
Compare.cpp
1 /*
2 MIT License
3 
4 Copyright (c) 2018 Brian T. Park
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 */
24 
25 /*
26 Design Notes:
27 ============
28 
29 Template Specialization:
30 -----------------------
31 One way to implement the compareEqual() for these types is to use template
32 specialization. The problem with Template specialization is that templates
33 use strict type matching, and does not perform the normal implicit type
34 conversion, including const-casting. Therefore, all of the various c-style
35 string types, for example:
36 
37  - char*
38  - const char*
39  - char[1]
40  - char[N]
41  - const char[1]
42  - const char[N]
43 
44 are considered to be different types under the C++ templating system. This
45 causes a combinatorial explosion of template specialization which produces
46 code that is difficult to understand, test and maintain.
47 An example can be seen in the Compare.h file of the ArduinoUnit project:
48 https://github.com/mmurdoch/arduinounit/blob/master/src/ArduinoUnitUtility/Compare.h
49 
50 Function Overloading:
51 ---------------------
52 In this project, I used function overloading instead of template
53 specialization. Function overloading handles c-style strings (i.e. character
54 arrays) naturally, in the way most users expect. For example, (char*) is
55 automarically cast to (const char*), and (char[N]) is autonmatically
56 cast to (const char*).
57 
58 For the primitive value types (e.g. (char), (int), (unsigned char), etc.) I
59 attempted to use a generic templatized version, using sonmething like:
60 
61  template<typename T>
62  compareEqual(const T& a, const T& b) { ... }
63 
64 However, this template introduced this method:
65 
66  compareEqual(char* const& a, char* const& b);
67 
68 that seemed to take precedence over the explicitly defined overload:
69 
70  compareEqual(const char* a, const char*b);
71 
72 When the compareEqual() method is called with a (char*) or a (char[N]),
73 like this:
74 
75  char a[3] = {...};
76  char b[4] = {...};
77  compareEqual(a, b);
78 
79 this calls compareEqual(char* const&, const* const&), which is the wrong
80 version for a c-style string. The only way I could get this to work was to
81 avoid templates completely and manually define all the function overloads
82 even for primitive integer types.
83 
84 Implicit Conversions:
85 ---------------------
86 For basic primitive types, I depend on some casts to avoid having to define
87 some functions. I assume that signed and unsigned integers smaller or equal
88 to (int) will be converted to an (int) to match compareEqual(int, int).
89 
90 I provided an explicit compareEqual(char, char) overload because in C++, a
91 (char) type is distinct from (signed char) and (unsigned char).
92 
93 Technically, there should be a (long long) version and an (unsigned long
94 long) version of compareEqual(). However, it turns out that the Arduino
95 Print::print() method does not have an overload for these types, so it would
96 not do us much good to provide an assertEqual() or compareEqual() for the
97 (long long) and (unsigned long long) types.
98 
99 Custom Assert and Compare Functions:
100 ------------------------------------
101 Another advantage of using function overloading instead of template
102 specialization is that the user is able to add additional function overloads
103 into the 'aunit' namespace. This should allow the user to define the various
104 comporeXxx() and assertXxx() functions for a custom class. I have not
105 tested this though.
106 
107 Comparing Flash Strings:
108 ------------------------
109 Flash memory must be read using 4-byte alignment on the ESP8266. AVR doesn't
110 care. Teensy-ARM fakes the flash memory API but really just uses the normal
111 static RAM. The following code for comparing two (__FlashStringHelper*)
112 against each other will work for all 3 environments.
113 
114 Inlining:
115 --------
116 Even though most of these functions are one-liners, there is no advantage to
117 inlining them because they are almost always used through a function pointer.
118 */
119 
120 #include <string.h>
121 #include <WString.h>
122 #include "Flash.h"
123 #include "Compare.h"
124 #include "FCString.h"
125 
126 namespace aunit {
127 namespace internal {
128 
129 class FCString;
130 
131 // compareString()
132 
133 int compareString(const char* a, const char* b) {
134  return strcmp(a, b);
135 }
136 
137 int compareString(const char* a, const String& b) {
138  return strcmp(a, b.c_str());
139 }
140 
141 int compareString(const char* a, const __FlashStringHelper* b) {
142  return strcmp_P(a, (const char*)b);
143 }
144 
145 int compareString(const String& a, const char* b) {
146  return strcmp(a.c_str(), b);
147 }
148 
149 int compareString(const String& a, const String& b) {
150  return a.compareTo(b);
151 }
152 
153 int compareString(const String& a, const __FlashStringHelper* b) {
154  return strcmp_P(a.c_str(), (const char*)b);
155 }
156 
157 int compareString(const __FlashStringHelper* a, const char* b) {
158  return -strcmp_P(b, (const char*) a);
159 }
160 
161 // On ESP8266, pgm_read_byte() already takes care of 4-byte alignment, and
162 // memcpy_P(s, p, 4) makes 4 calls to pgm_read_byte() anyway, so don't bother
163 // optimizing for 4-byte alignment here.
164 int compareString(const __FlashStringHelper* a, const __FlashStringHelper* b) {
165  const char* aa = reinterpret_cast<const char*>(a);
166  const char* bb = reinterpret_cast<const char*>(b);
167 
168  while (true) {
169  uint8_t ca = pgm_read_byte(aa);
170  uint8_t cb = pgm_read_byte(bb);
171  if (ca != cb) return (int) ca - (int) cb;
172  if (ca == '\0') return 0;
173  aa++;
174  bb++;
175  }
176 }
177 
178 int compareString(const __FlashStringHelper* a, const String& b) {
179  return -strcmp_P(b.c_str(), (const char*)a);
180 }
181 
182 int compareString(const FCString& a, const FCString& b) {
183  if (a.getType() == FCString::kCStringType) {
184  if (b.getType() == FCString::kCStringType) {
185  return compareString(a.getCString(), b.getCString());
186  } else {
187  return compareString(a.getCString(), b.getFString());
188  }
189  } else {
190  if (b.getType() == FCString::kCStringType) {
191  return compareString(a.getFString(), b.getCString());
192  } else {
193  return compareString(a.getFString(), b.getFString());
194  }
195  }
196 }
197 
198 // compareStringN()
199 
200 int compareStringN(const char* a, const char* b, size_t n) {
201  return strncmp(a, b, n);
202 }
203 
204 int compareStringN(const char* a, const __FlashStringHelper* b, size_t n) {
205  return strncmp_P(a, (const char*)b, n);
206 }
207 
208 int compareStringN(const __FlashStringHelper* a, const char* b, size_t n) {
209  return -strncmp_P(b, (const char*)a, n);
210 }
211 
212 // On ESP8266, pgm_read_byte() already takes care of 4-byte alignment, and
213 // memcpy_P(s, p, 4) makes 4 calls to pgm_read_byte() anyway, so don't bother
214 // optimizing for 4-byte alignment here.
215 int compareStringN(const __FlashStringHelper* a, const __FlashStringHelper* b,
216  size_t n) {
217  const char* aa = reinterpret_cast<const char*>(a);
218  const char* bb = reinterpret_cast<const char*>(b);
219 
220  while (n > 0) {
221  uint8_t ca = pgm_read_byte(aa);
222  uint8_t cb = pgm_read_byte(bb);
223  if (ca != cb) return (int) ca - (int) cb;
224  if (ca == '\0') return 0;
225  aa++;
226  bb++;
227  n--;
228  }
229  return 0;
230 }
231 
232 int compareStringN(const FCString& a, const char* b, size_t n) {
233  if (a.getType() == FCString::kCStringType) {
234  return compareStringN(a.getCString(), b, n);
235  } else {
236  return compareStringN(a.getFString(), b, n);
237  }
238 }
239 
240 int compareStringN(const FCString& a, const __FlashStringHelper* b, size_t n) {
241  if (a.getType() == FCString::kCStringType) {
242  return compareStringN(a.getCString(), b, n);
243  } else {
244  return compareStringN(a.getFString(), b, n);
245  }
246 }
247 
248 // compareEqual()
249 
250 bool compareEqual(bool a, bool b) {
251  return (a == b);
252 }
253 
254 bool compareEqual(char a, char b) {
255  return (a == b);
256 }
257 
258 bool compareEqual(int a, int b) {
259  return (a == b);
260 }
261 
262 bool compareEqual(unsigned int a, unsigned int b) {
263  return (a == b);
264 }
265 
266 bool compareEqual(long a, long b) {
267  return (a == b);
268 }
269 
270 bool compareEqual(unsigned long a, unsigned long b) {
271  return (a == b);
272 }
273 
274 bool compareEqual(double a, double b) {
275  return (a == b);
276 }
277 
278 bool compareEqual(const char* a, const char* b) {
279  return compareString(a, b) == 0;
280 }
281 
282 bool compareEqual(const char* a, const String& b) {
283  return compareString(a, b) == 0;
284 }
285 
286 bool compareEqual(const char* a, const __FlashStringHelper* b) {
287  return compareString(a, b) == 0;
288 }
289 
290 bool compareEqual(const __FlashStringHelper* a, const char* b) {
291  return compareString(a, b) == 0;
292 }
293 
294 bool compareEqual(const __FlashStringHelper* a, const __FlashStringHelper* b) {
295  return compareString(a, b) == 0;
296 }
297 
298 bool compareEqual(const __FlashStringHelper* a, const String& b) {
299  return compareString(a, b) == 0;
300 }
301 
302 bool compareEqual(const String& a, const char* b) {
303  return compareString(a, b) == 0;
304 }
305 
306 bool compareEqual(const String& a, const String& b) {
307  return compareString(a, b) == 0;
308 }
309 
310 bool compareEqual(const String& a, const __FlashStringHelper* b) {
311  return compareString(a, b) == 0;
312 }
313 
314 // compareLess()
315 
316 bool compareLess(bool a, bool b) {
317  return (a < b);
318 }
319 
320 bool compareLess(char a, char b) {
321  return (a < b);
322 }
323 
324 bool compareLess(int a, int b) {
325  return (a < b);
326 }
327 
328 bool compareLess(unsigned int a, unsigned int b) {
329  return (a < b);
330 }
331 
332 bool compareLess(long a, long b) {
333  return (a < b);
334 }
335 
336 bool compareLess(unsigned long a, unsigned long b) {
337  return (a < b);
338 }
339 
340 bool compareLess(double a, double b) {
341  return (a < b);
342 }
343 
344 bool compareLess(const char* a, const char* b) {
345  return compareString(a, b) < 0;
346 }
347 
348 bool compareLess(const char* a, const String& b) {
349  return compareString(a, b) < 0;
350 }
351 
352 bool compareLess(const char* a, const __FlashStringHelper* b) {
353  return compareString(a, b) < 0;
354 }
355 
356 bool compareLess(const __FlashStringHelper* a, const char* b) {
357  return compareString(a, b) < 0;
358 }
359 
360 bool compareLess(
361  const __FlashStringHelper* a, const __FlashStringHelper* b) {
362  return compareString(a, b) < 0;
363 }
364 
365 bool compareLess(const __FlashStringHelper* a, const String& b) {
366  return compareString(a, b) < 0;
367 }
368 
369 bool compareLess(const String& a, const char* b) {
370  return compareString(a, b) < 0;
371 }
372 
373 bool compareLess(const String& a, const String& b) {
374  return compareString(a, b) < 0;
375 }
376 
377 bool compareLess(const String& a, const __FlashStringHelper* b) {
378  return compareString(a, b) < 0;
379 }
380 
381 // compareMore()
382 
383 bool compareMore(bool a, bool b) {
384  return (a > b);
385 }
386 
387 bool compareMore(char a, char b) {
388  return (a > b);
389 }
390 
391 bool compareMore(int a, int b) {
392  return (a > b);
393 }
394 
395 bool compareMore(unsigned int a, unsigned int b) {
396  return (a > b);
397 }
398 
399 bool compareMore(long a, long b) {
400  return (a > b);
401 }
402 
403 bool compareMore(unsigned long a, unsigned long b) {
404  return (a > b);
405 }
406 
407 bool compareMore(double a, double b) {
408  return (a > b);
409 }
410 
411 bool compareMore(const char* a, const char* b) {
412  return compareString(a, b) > 0;
413 }
414 
415 bool compareMore(const char* a, const String& b) {
416  return compareString(a, b) > 0;
417 }
418 
419 bool compareMore(const char* a, const __FlashStringHelper* b) {
420  return compareString(a, b) > 0;
421 }
422 
423 bool compareMore(const __FlashStringHelper* a, const char* b) {
424  return compareString(a, b) > 0;
425 }
426 
427 bool compareMore(const __FlashStringHelper* a, const __FlashStringHelper* b) {
428  return compareString(a, b) > 0;
429 }
430 
431 bool compareMore(const __FlashStringHelper* a, const String& b) {
432  return compareString(a, b) > 0;
433 }
434 
435 bool compareMore(const String& a, const char* b) {
436  return compareString(a, b) > 0;
437 }
438 
439 bool compareMore(const String& a, const String& b) {
440  return compareString(a, b) > 0;
441 }
442 
443 bool compareMore(const String& a, const __FlashStringHelper* b) {
444  return compareString(a, b) > 0;
445 }
446 
447 // compareLessOrEqual
448 
449 bool compareLessOrEqual(bool a, bool b) {
450  return (a <= b);
451 }
452 
453 bool compareLessOrEqual(char a, char b) {
454  return (a <= b);
455 }
456 
457 bool compareLessOrEqual(int a, int b) {
458  return (a <= b);
459 }
460 
461 bool compareLessOrEqual(unsigned int a, unsigned int b) {
462  return (a <= b);
463 }
464 
465 bool compareLessOrEqual(long a, long b) {
466  return (a <= b);
467 }
468 
469 bool compareLessOrEqual(unsigned long a, unsigned long b) {
470  return (a <= b);
471 }
472 
473 bool compareLessOrEqual(double a, double b) {
474  return (a <= b);
475 }
476 
477 bool compareLessOrEqual(const char* a, const char* b) {
478  return compareString(a, b) <= 0;
479 }
480 
481 bool compareLessOrEqual(const char* a, const String& b) {
482  return compareString(a, b) <= 0;
483 }
484 
485 bool compareLessOrEqual(const char* a, const __FlashStringHelper* b) {
486  return compareString(a, b) <= 0;
487 }
488 
489 bool compareLessOrEqual(const __FlashStringHelper* a, const char* b) {
490  return compareString(a, b) <= 0;
491 }
492 
493 bool compareLessOrEqual(
494  const __FlashStringHelper* a, const __FlashStringHelper* b) {
495  return compareString(a, b) <= 0;
496 }
497 
498 bool compareLessOrEqual(const __FlashStringHelper* a, const String& b) {
499  return compareString(a, b) <= 0;
500 }
501 
502 bool compareLessOrEqual(const String& a, const char* b) {
503  return compareString(a, b) <= 0;
504 }
505 
506 bool compareLessOrEqual(const String& a, const String& b) {
507  return compareString(a, b) <= 0;
508 }
509 
510 bool compareLessOrEqual(const String& a, const __FlashStringHelper* b) {
511  return compareString(a, b) <= 0;
512 }
513 
514 // compareMoreOrEqual
515 
516 bool compareMoreOrEqual(bool a, bool b) {
517  return (a >= b);
518 }
519 
520 bool compareMoreOrEqual(char a, char b) {
521  return (a >= b);
522 }
523 
524 bool compareMoreOrEqual(int a, int b) {
525  return (a >= b);
526 }
527 
528 bool compareMoreOrEqual(unsigned int a, unsigned int b) {
529  return (a >= b);
530 }
531 
532 bool compareMoreOrEqual(long a, long b) {
533  return (a >= b);
534 }
535 
536 bool compareMoreOrEqual(unsigned long a, unsigned long b) {
537  return (a >= b);
538 }
539 
540 bool compareMoreOrEqual(double a, double b) {
541  return (a >= b);
542 }
543 
544 bool compareMoreOrEqual(const char* a, const char* b) {
545  return compareString(a, b) >= 0;
546 }
547 
548 bool compareMoreOrEqual(const char* a, const String& b) {
549  return compareString(a, b) >= 0;
550 }
551 
552 bool compareMoreOrEqual(const char* a, const __FlashStringHelper* b) {
553  return compareString(a, b) >= 0;
554 }
555 
556 bool compareMoreOrEqual(const __FlashStringHelper* a, const char* b) {
557  return compareString(a, b) >= 0;
558 }
559 
560 bool compareMoreOrEqual(
561  const __FlashStringHelper* a, const __FlashStringHelper* b) {
562  return compareString(a, b) >= 0;
563 }
564 
565 bool compareMoreOrEqual(const __FlashStringHelper* a, const String& b) {
566  return compareString(a, b) >= 0;
567 }
568 
569 bool compareMoreOrEqual(const String& a, const char* b) {
570  return compareString(a, b) >= 0;
571 }
572 
573 bool compareMoreOrEqual(const String& a, const String& b) {
574  return compareString(a, b) >= 0;
575 }
576 
577 bool compareMoreOrEqual(const String& a, const __FlashStringHelper* b) {
578  return compareString(a, b) >= 0;
579 }
580 
581 // compareNotEqual
582 
583 bool compareNotEqual(bool a, bool b) {
584  return (a != b);
585 }
586 
587 bool compareNotEqual(char a, char b) {
588  return (a != b);
589 }
590 
591 bool compareNotEqual(int a, int b) {
592  return (a != b);
593 }
594 
595 bool compareNotEqual(unsigned int a, unsigned int b) {
596  return (a != b);
597 }
598 
599 bool compareNotEqual(long a, long b) {
600  return (a != b);
601 }
602 
603 bool compareNotEqual(unsigned long a, unsigned long b) {
604  return (a != b);
605 }
606 
607 bool compareNotEqual(double a, double b) {
608  return (a != b);
609 }
610 
611 bool compareNotEqual(const char* a, const char* b) {
612  return compareString(a, b) != 0;
613 }
614 
615 bool compareNotEqual(const char* a, const String& b) {
616  return compareString(a, b) != 0;
617 }
618 
619 bool compareNotEqual(const char* a, const __FlashStringHelper* b) {
620  return compareString(a, b) != 0;
621 }
622 
623 bool compareNotEqual(const __FlashStringHelper* a, const char* b) {
624  return compareString(a, b) != 0;
625 }
626 
627 bool compareNotEqual(
628  const __FlashStringHelper* a, const __FlashStringHelper* b) {
629  return compareString(a, b) != 0;
630 }
631 
632 bool compareNotEqual(const __FlashStringHelper* a, const String& b) {
633  return compareString(a, b) != 0;
634 }
635 
636 bool compareNotEqual(const String& a, const char* b) {
637  return compareString(a, b) != 0;
638 }
639 
640 bool compareNotEqual(const String& a, const String& b) {
641  return compareString(a, b) != 0;
642 }
643 
644 bool compareNotEqual(const String& a, const __FlashStringHelper* b) {
645  return compareString(a, b) != 0;
646 }
647 
648 }
649 }
This file provides overloaded compareXxx(a, b) functions which are used by the various assertXxx(a...
Various macros to smooth over the differences among the various platforms with regards to their suppo...