Skip to content

Commit 20da521

Browse files
committed
tests/getvaluetest.c: check different methods to combine two "wire" bytes into a lenght word (follows up for #1320), hopefully all work the same on all architectures
1 parent b5b1585 commit 20da521

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed

tests/getvaluetest.c

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*
1111
* Copyright (C)
1212
* 2021 Nick Briggs <[email protected]>
13+
* 2022 Jim Klimov <[email protected]>
1314
*
1415
* This program is free software; you can redistribute it and/or modify
1516
* it under the terms of the GNU General Public License as published by
@@ -34,6 +35,7 @@
3435
#include <stdlib.h>
3536
#include <string.h>
3637
#include "hidtypes.h"
38+
#include "usb-common.h"
3739
#include "common.h"
3840

3941
void GetValue(const unsigned char *Buf, HIDData_t *pData, long *pValue);
@@ -125,6 +127,106 @@ static int RunBuiltInTests(char *argv[]) {
125127
exitStatus = 1;
126128
}
127129
}
130+
131+
/* Emulate rdlen calculations in libusb{0,1}.c or
132+
* langid calculations in nutdrv_qx.c; in these
133+
* cases we take two bytes (cast from usb_ctrl_char
134+
* type, may be signed depending on used API version)
135+
* from the protocol buffer, and build a platform
136+
* dependent representation of a two-byte word.
137+
*/
138+
usb_ctrl_char bufC[2];
139+
signed char bufS[2];
140+
unsigned char bufU[2];
141+
int rdlen;
142+
143+
/* Example from issue https://github.com/networkupstools/nut/issues/1261
144+
* where resulting length 0x01a9 should be "425" but ended up "-87" */
145+
bufC[0] = (usb_ctrl_char)0xa9;
146+
bufC[1] = (usb_ctrl_char)0x01;
147+
148+
bufS[0] = (signed char)0xa9;
149+
bufS[1] = (signed char)0x01;
150+
151+
bufU[0] = (unsigned char)0xa9;
152+
bufU[1] = (unsigned char)0x01;
153+
154+
/* Check different conversion methods and hope current build CPU,
155+
* C implementation etc. do not mess up bit-shifting vs rotation,
156+
* zeroing high bits, int type width extension et al. If something
157+
* is mismatched below, the production NUT code may need adaptations
158+
* for that platform to count stuff correctly!
159+
*/
160+
printf("\nTesting bit-shifting approaches used in codebase to get 2-byte int lengths from wire bytes:\n");
161+
printf("(Expected correct value is '425', incorrect '-87' or other)\n");
162+
163+
#define REPORT_VERDICT(expected) { if (expected) { printf(" - PASS\n"); } else { printf(" - FAIL\n"); exitStatus = 1; } }
164+
165+
rdlen = bufC[0] | (bufC[1] << 8);
166+
printf(" * reference: no casting, usb_ctrl_char :\t%d\t(depends on libusb API built against)", rdlen);
167+
REPORT_VERDICT (rdlen == 425 || rdlen == -87)
168+
169+
rdlen = bufS[0] | (bufS[1] << 8);
170+
printf(" * reference: no casting, signed char :\t%d\t(expected '-87' here)", rdlen);
171+
REPORT_VERDICT (rdlen == -87)
172+
173+
rdlen = bufU[0] | (bufU[1] << 8);
174+
printf(" * reference: no casting, unsigned char :\t%d\t(expected '425')", rdlen);
175+
REPORT_VERDICT (rdlen == 425)
176+
177+
178+
rdlen = (uint8_t)bufC[0] | ((uint8_t)bufC[1] << 8);
179+
printf(" * uint8_t casting, usb_ctrl_char :\t%d", rdlen);
180+
REPORT_VERDICT (rdlen == 425)
181+
182+
rdlen = (uint8_t)bufS[0] | ((uint8_t)bufS[1] << 8);
183+
printf(" * uint8_t casting, signed char :\t%d", rdlen);
184+
REPORT_VERDICT (rdlen == 425)
185+
186+
rdlen = (uint8_t)bufU[0] | ((uint8_t)bufU[1] << 8);
187+
printf(" * uint8_t casting, unsigned char :\t%d", rdlen);
188+
REPORT_VERDICT (rdlen == 425)
189+
190+
191+
rdlen = ((uint8_t)bufC[0]) | (((uint8_t)bufC[1]) << 8);
192+
printf(" * uint8_t casting with parentheses, usb_ctrl_char :\t%d", rdlen);
193+
REPORT_VERDICT (rdlen == 425)
194+
195+
rdlen = ((uint8_t)bufS[0]) | (((uint8_t)bufS[1]) << 8);
196+
printf(" * uint8_t casting with parentheses, signed char :\t%d", rdlen);
197+
REPORT_VERDICT (rdlen == 425)
198+
199+
rdlen = ((uint8_t)bufU[0]) | (((uint8_t)bufU[1]) << 8);
200+
printf(" * uint8_t casting with parentheses, unsigned char :\t%d", rdlen);
201+
REPORT_VERDICT (rdlen == 425)
202+
203+
204+
rdlen = ((uint16_t)(bufC[0]) & 0x00FF) | (((uint16_t)(bufC[1]) & 0x00FF) << 8);
205+
printf(" * uint16_t casting with 8-bit mask, usb_ctrl_char :\t%d", rdlen);
206+
REPORT_VERDICT (rdlen == 425)
207+
208+
rdlen = ((uint16_t)(bufS[0]) & 0x00FF) | (((uint16_t)(bufS[1]) & 0x00FF) << 8);
209+
printf(" * uint16_t casting with 8-bit mask, signed char :\t%d", rdlen);
210+
REPORT_VERDICT (rdlen == 425)
211+
212+
rdlen = ((uint16_t)(bufU[0]) & 0x00FF) | (((uint16_t)(bufU[1]) & 0x00FF) << 8);
213+
printf(" * uint16_t casting with 8-bit mask, unsigned char :\t%d", rdlen);
214+
REPORT_VERDICT (rdlen == 425)
215+
216+
217+
rdlen = 256 * (uint8_t)(bufC[1]) + (uint8_t)(bufC[0]);
218+
printf(" * uint8_t casting with multiplication, usb_ctrl_char :\t%d", rdlen);
219+
REPORT_VERDICT (rdlen == 425)
220+
221+
rdlen = 256 * (uint8_t)(bufS[1]) + (uint8_t)(bufS[0]);
222+
printf(" * uint8_t casting with multiplication, signed char :\t%d", rdlen);
223+
REPORT_VERDICT (rdlen == 425)
224+
225+
rdlen = 256 * (uint8_t)(bufU[1]) + (uint8_t)(bufU[0]);
226+
printf(" * uint8_t casting with multiplication, unsigned char :\t%d", rdlen);
227+
REPORT_VERDICT (rdlen == 425)
228+
229+
128230
return (exitStatus);
129231
}
130232

0 commit comments

Comments
 (0)