Skip to content

Commit 3d3bdc7

Browse files
committed
preserve a<b semantics in widening
1 parent 60409b9 commit 3d3bdc7

File tree

3 files changed

+315
-1
lines changed

3 files changed

+315
-1
lines changed

firmware/firmware.ino

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,3 +621,51 @@ test(compileTestOk) {
621621
assertEqual(expect, adjustableConfig.getDoubleClickDelay());
622622
assertEqual(uint16_t(3), adjustableConfig.getDoubleClickDelay());
623623
}
624+
625+
#if defined(__AVR__)
626+
test(case_2_intended_to_pass_but_fails_on_avr)
627+
{
628+
verbosity |= TEST_VERBOSITY_ASSERTIONS_PASSED;
629+
630+
int8_t end = 1;
631+
int8_t start = 2;
632+
uint16_t limit = 30;
633+
634+
// Two's complement rollover was not intended to happen, but happens on AVR
635+
// with 16-bit integers. This is human-error, and assertLess() does the
636+
// correct thing by failing.
637+
if (end - start < limit) {
638+
Serial.println("The following assertLess() should pass on AVR");
639+
} else {
640+
Serial.println("The following assertLess() should fail on AVR");
641+
}
642+
643+
assertLess(end - start, limit);
644+
}
645+
646+
#elif defined(__arm__) || defined(ESP8266) || !defined(ARDUINO)
647+
648+
test(case_2_intended_to_pass_and_should_pass_on_32_bit)
649+
{
650+
verbosity |= TEST_VERBOSITY_ASSERTIONS_PASSED;
651+
652+
int8_t end = 1;
653+
int8_t start = 2;
654+
uint16_t limit = 30;
655+
656+
// Two's complement rollover was not intended and this code was intended to
657+
// work on a 32-bit processor. Both arguments should be promoted to a 32-bit
658+
// int, and the assertLess() should pass. But something is wrong with the
659+
// assertLess() on a 32-bit processor because it actually fails.
660+
if (end - start < limit) {
661+
Serial.println("The following assertLess() should pass on 32-bit MCUs");
662+
} else {
663+
Serial.println("The following assertLess() should fail on 32-bit MCUs");
664+
}
665+
666+
assertLess(end - start, limit);
667+
}
668+
#endif
669+
670+
671+

src/ArduinoUnit.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ is in another file (or defined after the assertion on it). */
566566

567567
// helper define for the operators below
568568
#define assertOpMsg(arg1,op,op_name,arg2, message) \
569-
do { if (!Test::assertion< ArduinoUnitArgType(arg1) , ArduinoUnitArgType(arg2) > (ARDUINO_UNIT_STRING(__FILE__),__LINE__,ARDUINO_UNIT_STRING(#arg1),(arg1),ARDUINO_UNIT_STRING(op_name),op,ARDUINO_UNIT_STRING(#arg2),(arg2),message)) return; } while (0)
569+
do { if (!Test::assertion< ArduinoUnitArgTypes(arg1,arg1)::A , ArduinoUnitArgTypes(arg1,arg2)::B > (ARDUINO_UNIT_STRING(__FILE__),__LINE__,ARDUINO_UNIT_STRING(#arg1),(arg1),ARDUINO_UNIT_STRING(op_name),op,ARDUINO_UNIT_STRING(#arg2),(arg2),message)) return; } while (0)
570570

571571
#define assertOp_5(a1,op,op_name,arg2,message) assertOpMsg(a1,op,op_name,arg2,[&](bool ok)->void { (void)ok; Test::Printer() << ARDUINO_UNIT_STRING(" [") << message << ARDUINO_UNIT_STRING("]"); })
572572
#define assertOp_4(a1,op,op_name,arg2) assertOpMsg(a1,op,op_name,arg2,&Test::noMessage)

src/ArduinoUnitUtility/ArduinoUnitWiden.h

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,271 @@ template< > struct ArduinoUnitWiden < char * > { typedef ArduinoUnitString type;
2323
template< > struct ArduinoUnitWiden < char [] > { typedef ArduinoUnitString type; };
2424
template<int N> struct ArduinoUnitWiden < char [N] > { typedef ArduinoUnitString type; };
2525

26+
//
27+
// Welcome to the Arduino Unit trailer park... This is the same idea
28+
// as Widen, but takes both argument types into account.
29+
//
30+
template <typename _A, typename _B> struct ArduinoUnitDoubleWide {
31+
typedef _A A;
32+
typedef _B B;
33+
};
34+
35+
// signed types
36+
37+
template < > struct ArduinoUnitDoubleWide < char , char > {
38+
typedef int A;
39+
typedef int B;
40+
};
41+
42+
template < > struct ArduinoUnitDoubleWide < char , short > {
43+
typedef int A;
44+
typedef int B;
45+
};
46+
47+
template < > struct ArduinoUnitDoubleWide < char , int > {
48+
typedef int A;
49+
typedef int B;
50+
};
51+
52+
template < > struct ArduinoUnitDoubleWide < char , long > {
53+
typedef long A;
54+
typedef long B;
55+
};
56+
57+
template < > struct ArduinoUnitDoubleWide < char , long long > {
58+
typedef long long A;
59+
typedef long long B;
60+
};
61+
62+
template < > struct ArduinoUnitDoubleWide < short , char > {
63+
typedef int A;
64+
typedef int B;
65+
};
66+
67+
template < > struct ArduinoUnitDoubleWide < short , short > {
68+
typedef int A;
69+
typedef int B;
70+
};
71+
72+
template < > struct ArduinoUnitDoubleWide < short , int > {
73+
typedef int A;
74+
typedef int B;
75+
};
76+
77+
template < > struct ArduinoUnitDoubleWide < short , long > {
78+
typedef long A;
79+
typedef long B;
80+
};
81+
82+
template < > struct ArduinoUnitDoubleWide < short , long long > {
83+
typedef long long A;
84+
typedef long long B;
85+
};
86+
87+
template < > struct ArduinoUnitDoubleWide < int , char > {
88+
typedef int A;
89+
typedef int B;
90+
};
91+
92+
template < > struct ArduinoUnitDoubleWide < int , short > {
93+
typedef int A;
94+
typedef int B;
95+
};
96+
97+
template < > struct ArduinoUnitDoubleWide < int , int > {
98+
typedef int A;
99+
typedef int B;
100+
};
101+
102+
template < > struct ArduinoUnitDoubleWide < int , long > {
103+
typedef long A;
104+
typedef long B;
105+
};
106+
107+
template < > struct ArduinoUnitDoubleWide < int , long long > {
108+
typedef long long A;
109+
typedef long long B;
110+
};
111+
112+
template < > struct ArduinoUnitDoubleWide < long , char > {
113+
typedef long A;
114+
typedef long B;
115+
};
116+
117+
template < > struct ArduinoUnitDoubleWide < long , short > {
118+
typedef long A;
119+
typedef long B;
120+
};
121+
122+
template < > struct ArduinoUnitDoubleWide < long , int > {
123+
typedef long A;
124+
typedef long B;
125+
};
126+
127+
template < > struct ArduinoUnitDoubleWide < long , long > {
128+
typedef long A;
129+
typedef long B;
130+
};
131+
132+
template < > struct ArduinoUnitDoubleWide < long , long long > {
133+
typedef long long A;
134+
typedef long long B;
135+
};
136+
137+
template < > struct ArduinoUnitDoubleWide < long long , char > {
138+
typedef long long A;
139+
typedef long long B;
140+
};
141+
142+
template < > struct ArduinoUnitDoubleWide < long long , short > {
143+
typedef long long A;
144+
typedef long long B;
145+
};
146+
147+
template < > struct ArduinoUnitDoubleWide < long long , int > {
148+
typedef long long A;
149+
typedef long long B;
150+
};
151+
152+
template < > struct ArduinoUnitDoubleWide < long long , long > {
153+
typedef long long A;
154+
typedef long long B;
155+
};
156+
157+
template < > struct ArduinoUnitDoubleWide < long long , long long > {
158+
typedef long long A;
159+
typedef long long B;
160+
};
161+
162+
163+
// unsigned types
164+
165+
template < > struct ArduinoUnitDoubleWide < unsigned char , unsigned char > {
166+
typedef unsigned int A;
167+
typedef unsigned int B;
168+
};
169+
170+
template < > struct ArduinoUnitDoubleWide < unsigned char , unsigned short > {
171+
typedef unsigned int A;
172+
typedef unsigned int B;
173+
};
174+
175+
template < > struct ArduinoUnitDoubleWide < unsigned char , unsigned int > {
176+
typedef unsigned int A;
177+
typedef unsigned int B;
178+
};
179+
180+
template < > struct ArduinoUnitDoubleWide < unsigned char , unsigned long > {
181+
typedef unsigned long A;
182+
typedef unsigned long B;
183+
};
184+
185+
template < > struct ArduinoUnitDoubleWide < unsigned char , unsigned long long > {
186+
typedef unsigned long long A;
187+
typedef unsigned long long B;
188+
};
189+
190+
template < > struct ArduinoUnitDoubleWide < unsigned short , unsigned char > {
191+
typedef unsigned int A;
192+
typedef unsigned int B;
193+
};
194+
195+
template < > struct ArduinoUnitDoubleWide < unsigned short , unsigned short > {
196+
typedef unsigned int A;
197+
typedef unsigned int B;
198+
};
199+
200+
template < > struct ArduinoUnitDoubleWide < unsigned short , unsigned int > {
201+
typedef unsigned int A;
202+
typedef unsigned int B;
203+
};
204+
205+
template < > struct ArduinoUnitDoubleWide < unsigned short , unsigned long > {
206+
typedef unsigned long A;
207+
typedef unsigned long B;
208+
};
209+
210+
template < > struct ArduinoUnitDoubleWide < unsigned short , unsigned long long > {
211+
typedef unsigned long long A;
212+
typedef unsigned long long B;
213+
};
214+
215+
template < > struct ArduinoUnitDoubleWide < unsigned int , unsigned char > {
216+
typedef unsigned int A;
217+
typedef unsigned int B;
218+
};
219+
220+
template < > struct ArduinoUnitDoubleWide < unsigned int , unsigned short > {
221+
typedef unsigned int A;
222+
typedef unsigned int B;
223+
};
224+
225+
template < > struct ArduinoUnitDoubleWide < unsigned int , unsigned int > {
226+
typedef unsigned int A;
227+
typedef unsigned int B;
228+
};
229+
230+
template < > struct ArduinoUnitDoubleWide < unsigned int , unsigned long > {
231+
typedef unsigned long A;
232+
typedef unsigned long B;
233+
};
234+
235+
template < > struct ArduinoUnitDoubleWide < unsigned int , unsigned long long > {
236+
typedef unsigned long long A;
237+
typedef unsigned long long B;
238+
};
239+
240+
template < > struct ArduinoUnitDoubleWide < unsigned long , unsigned char > {
241+
typedef unsigned long A;
242+
typedef unsigned long B;
243+
};
244+
245+
template < > struct ArduinoUnitDoubleWide < unsigned long , unsigned short > {
246+
typedef unsigned long A;
247+
typedef unsigned long B;
248+
};
249+
250+
template < > struct ArduinoUnitDoubleWide < unsigned long , unsigned int > {
251+
typedef unsigned long A;
252+
typedef unsigned long B;
253+
};
254+
255+
template < > struct ArduinoUnitDoubleWide < unsigned long , unsigned long > {
256+
typedef unsigned long A;
257+
typedef unsigned long B;
258+
};
259+
260+
template < > struct ArduinoUnitDoubleWide < unsigned long , unsigned long long > {
261+
typedef unsigned long long A;
262+
typedef unsigned long long B;
263+
};
264+
265+
template < > struct ArduinoUnitDoubleWide < unsigned long long , unsigned char > {
266+
typedef unsigned long long A;
267+
typedef unsigned long long B;
268+
};
269+
270+
template < > struct ArduinoUnitDoubleWide < unsigned long long , unsigned short > {
271+
typedef unsigned long long A;
272+
typedef unsigned long long B;
273+
};
274+
275+
template < > struct ArduinoUnitDoubleWide < unsigned long long , unsigned int > {
276+
typedef unsigned long long A;
277+
typedef unsigned long long B;
278+
};
279+
280+
template < > struct ArduinoUnitDoubleWide < unsigned long long , unsigned long > {
281+
typedef unsigned long long A;
282+
typedef unsigned long long B;
283+
};
284+
285+
template < > struct ArduinoUnitDoubleWide < unsigned long long , unsigned long long > {
286+
typedef unsigned long long A;
287+
typedef unsigned long long B;
288+
};
289+
26290
#define ArduinoUnitType(T) ArduinoUnitWiden < ArduinoUnitRemoveConstTemplate < ArduinoUnitRemoveReferenceTemplate < T >::type >::type >::type
27291
#define ArduinoUnitArgType(X) ArduinoUnitType(__typeof__(X))
292+
293+
#define ArduinoUnitArgTypes(X,Y) ArduinoUnitDoubleWide < ArduinoUnitArgType(X) , ArduinoUnitArgType(Y) >

0 commit comments

Comments
 (0)