Skip to content

Commit 526df1b

Browse files
committed
chore: increase coverage in n_request.c
1 parent b14a418 commit 526df1b

12 files changed

+1044
-203
lines changed

n_i2c.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ bool _i2cNoteReset(void)
301301
break;
302302
}
303303

304-
NOTE_C_LOG_DEBUG("retrying I2C interface reset...")
304+
NOTE_C_LOG_DEBUG("retrying I2C interface reset...");
305305
}
306306

307307
// Done with the I2C bus

n_request.c

Lines changed: 92 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,57 @@ NOTE_C_STATIC bool _crcError(char *json, uint16_t shouldBeSeqno);
3636
NOTE_C_STATIC bool notecardFirmwareSupportsCrc = false;
3737
#endif // !NOTE_C_LOW_MEM
3838

39+
/*!
40+
@internal
41+
42+
@brief Create a JSON object containing an error message.
43+
44+
Create a dynamically allocated `J` object containing a single string field
45+
"err" whose value is the passed in error message.
46+
47+
@param id The "id" from the original request that resulted in an error
48+
@param errmsg The error message.
49+
50+
@returns A `J` object with the "err" field populated.
51+
*/
52+
NOTE_C_STATIC J * _errDoc(uint32_t id, const char *errmsg)
53+
{
54+
J *rspdoc = JCreateObject();
55+
if (rspdoc != NULL) {
56+
JAddStringToObject(rspdoc, c_err, errmsg);
57+
JAddStringToObject(rspdoc, "src", "note-c");
58+
if (id) {
59+
JAddIntToObject(rspdoc, "id", id);
60+
}
61+
if (suppressShowTransactions == 0) {
62+
_DebugWithLevel(NOTE_C_LOG_LEVEL_ERROR, "[ERROR] ");
63+
_DebugWithLevel(NOTE_C_LOG_LEVEL_ERROR, "{\"err\":\"");
64+
_DebugWithLevel(NOTE_C_LOG_LEVEL_ERROR, errmsg);
65+
_DebugWithLevelLn(NOTE_C_LOG_LEVEL_ERROR, "\",\"src\":\"note-c\"}");
66+
}
67+
} else {
68+
NOTE_C_LOG_ERROR("Failed to allocate error document!");
69+
}
70+
71+
return rspdoc;
72+
}
73+
74+
/*!
75+
@brief Resume showing transaction details.
76+
*/
77+
void _noteResumeTransactionDebug(void)
78+
{
79+
suppressShowTransactions--;
80+
}
81+
82+
/*!
83+
@brief Suppress showing transaction details.
84+
*/
85+
void _noteSuspendTransactionDebug(void)
86+
{
87+
suppressShowTransactions++;
88+
}
89+
3990
/*!
4091
@internal
4192
@@ -92,55 +143,6 @@ NOTE_C_STATIC bool notecardFirmwareSupportsCrc = false;
92143
return result;
93144
}
94145

95-
/*!
96-
@internal
97-
98-
@brief Create a JSON object containing an error message.
99-
100-
Create a dynamically allocated `J` object containing a single string field
101-
"err" whose value is the passed in error message.
102-
103-
@param id The "id" from the original request that resulted in an error
104-
@param errmsg The error message.
105-
106-
@returns A `J` object with the "err" field populated.
107-
*/
108-
NOTE_C_STATIC J * errDoc(uint32_t id, const char *errmsg)
109-
{
110-
J *rspdoc = JCreateObject();
111-
if (rspdoc != NULL) {
112-
JAddStringToObject(rspdoc, c_err, errmsg);
113-
JAddStringToObject(rspdoc, "src", "note-c");
114-
if (id) {
115-
JAddIntToObject(rspdoc, "id", id);
116-
}
117-
if (suppressShowTransactions == 0) {
118-
_DebugWithLevel(NOTE_C_LOG_LEVEL_ERROR, "[ERROR] ");
119-
_DebugWithLevel(NOTE_C_LOG_LEVEL_ERROR, "{\"err\":\"");
120-
_DebugWithLevel(NOTE_C_LOG_LEVEL_ERROR, errmsg);
121-
_DebugWithLevelLn(NOTE_C_LOG_LEVEL_ERROR, "\",\"src\":\"note-c\"}");
122-
}
123-
}
124-
125-
return rspdoc;
126-
}
127-
128-
/*!
129-
@brief Suppress showing transaction details.
130-
*/
131-
void _noteSuspendTransactionDebug(void)
132-
{
133-
suppressShowTransactions++;
134-
}
135-
136-
/*!
137-
@brief Resume showing transaction details.
138-
*/
139-
void _noteResumeTransactionDebug(void)
140-
{
141-
suppressShowTransactions--;
142-
}
143-
144146
/*!
145147
@brief Suppress showing transaction details.
146148
*/
@@ -367,11 +369,18 @@ J *NoteRequestResponseWithRetry(J *req, uint32_t timeoutSeconds)
367369
if there was no response or if there was an error.
368370
369371
@note When a "cmd" is sent, it is not possible to determine if an error occurred.
372+
373+
@note Unlike the `NoteRequest*` functions, this function does not automatically
374+
free the request JSON string. It is not possible to know if the parameter
375+
is a string literal. As such, it is the caller's responsibility to manage
376+
the memory associated with the request string.
370377
*/
371378
char * NoteRequestResponseJSON(const char *reqJSON)
372379
{
373380
const uint32_t transactionTimeoutMs = (CARD_INTER_TRANSACTION_TIMEOUT_SEC * 1000);
374381
char *rspJSON = NULL;
382+
char *allocatedJSON = NULL; // required to free the string if it is not newline-terminated
383+
bool isCmdPipeline = false;
375384

376385
if (reqJSON == NULL) {
377386
return NULL;
@@ -396,25 +405,26 @@ char * NoteRequestResponseJSON(const char *reqJSON)
396405
// All JSON strings should be newline-terminated to meet the
397406
// specification, however this is required to ensure backward
398407
// compatibility with the previous implementation.
399-
const size_t tempLen = strlen(reqJSON);
400-
if (0 == tempLen) {
408+
const size_t allocLen = strlen(reqJSON);
409+
if (0 == allocLen) {
401410
NOTE_C_LOG_ERROR(ERRSTR("request: jsonbuf zero length", c_bad));
402411
break;
403412
}
404413

405414
NOTE_C_LOG_WARN(ERRSTR("Memory allocation due to malformed request (not newline-terminated)", c_bad));
406-
char * const temp = _Malloc(tempLen + 2); // +2 for newline and null-terminator
407-
if (temp == NULL) {
415+
allocatedJSON = _Malloc(allocLen + 2); // +2 for newline and null-terminator
416+
if (allocatedJSON == NULL) {
408417
NOTE_C_LOG_ERROR(ERRSTR("request: jsonbuf malloc failed", c_mem));
409418
break;
410419
}
411420

412-
memcpy(temp, reqJSON, tempLen);
413-
temp[tempLen] = '\n';
414-
temp[tempLen + 1] = '\0';
415-
reqJSON = temp;
416-
endPtr = &temp[tempLen];
421+
memcpy(allocatedJSON, reqJSON, allocLen);
422+
allocatedJSON[allocLen] = '\n';
423+
allocatedJSON[allocLen + 1] = '\0';
424+
reqJSON = allocatedJSON;
425+
endPtr = &allocatedJSON[allocLen];
417426
} else {
427+
isCmdPipeline = !(strlen(newlinePtr) == 1);
418428
endPtr = newlinePtr;
419429
}
420430
const size_t reqLen = ((endPtr - reqJSON) + 1);
@@ -439,15 +449,17 @@ char * NoteRequestResponseJSON(const char *reqJSON)
439449
const char *errstr = _Transaction(reqJSON, reqLen, &rspJSON, transactionTimeoutMs);
440450
if (errstr != NULL) {
441451
NOTE_C_LOG_ERROR(errstr);
452+
453+
// Extract ID from the request JSON, if present
442454
uint32_t id = 0;
443-
if (reqJSON != NULL) {
444-
J *req = JParse(reqJSON);
445-
if (req != NULL) {
446-
id = JGetInt(req, "id");
447-
JDelete(req);
448-
}
455+
J *req = JParse(reqJSON);
456+
if (req != NULL) {
457+
id = JGetInt(req, "id");
458+
JDelete(req);
449459
}
450-
J *errdoc = errDoc(id, errstr);
460+
461+
// Use _errDoc() to create a well-formed JSON error string
462+
J *errdoc = _errDoc(id, errstr);
451463
if (errdoc != NULL) {
452464
char *errdocJSON = JPrintUnformatted(errdoc);
453465
JDelete(errdoc);
@@ -463,25 +475,31 @@ char * NoteRequestResponseJSON(const char *reqJSON)
463475
}
464476
}
465477
}
466-
if (NULL == newlinePtr) {
467-
_Free((void *)reqJSON);
478+
if (allocatedJSON) {
479+
_Free((void *)allocatedJSON);
480+
allocatedJSON = NULL;
468481
}
469482
break;
470483
} else {
471484
// If it's a command, the Notecard will not respond, so we pass
472485
// NULL for the response parameter.
473486
const char *errstr = _Transaction(reqJSON, reqLen, NULL, transactionTimeoutMs);
474-
reqJSON = (endPtr + 1);
487+
reqJSON = (endPtr + 1); // Move to the next command in the pipeline
475488
if (errstr != NULL) {
476489
NOTE_C_LOG_ERROR(errstr);
477490
}
478491
}
479492

480493
// Clean up if we allocated a new string
481-
if (NULL == newlinePtr) {
482-
_Free((void *)reqJSON);
494+
(void)isCmdPipeline;
495+
if (allocatedJSON) {
496+
_Free((void *)allocatedJSON);
497+
break;
483498
}
484-
}
499+
if (!isCmdPipeline) {
500+
break;
501+
}
502+
} // for(;;)
485503

486504
_UnlockNote();
487505
_TransactionStop();
@@ -567,7 +585,7 @@ J *_noteTransactionShouldLock(J *req, bool lockNotecard)
567585
NOTE_C_LOG_ERROR(errStr);
568586
return NULL;
569587
}
570-
return errDoc(id, errStr);
588+
return _errDoc(id, errStr);
571589
}
572590

573591
// Inject the user agent object only when we're doing a `hub.set` and
@@ -596,7 +614,7 @@ J *_noteTransactionShouldLock(J *req, bool lockNotecard)
596614
NOTE_C_LOG_ERROR(errStr);
597615
return NULL;
598616
}
599-
return errDoc(id, errStr);
617+
return _errDoc(id, errStr);
600618
}
601619
}
602620

@@ -788,7 +806,7 @@ J *_noteTransactionShouldLock(J *req, bool lockNotecard)
788806
rsp = NULL;
789807
}
790808
NoteResetRequired(); // queue up a reset
791-
J *errRsp = errDoc(id, errStr);
809+
J *errRsp = _errDoc(id, errStr);
792810
if (lockNotecard) {
793811
_UnlockNote();
794812
}

n_serial.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ bool _serialNoteReset(void)
190190
return false;
191191
}
192192

193-
NOTE_C_LOG_DEBUG("retrying Serial interface reset.")
193+
NOTE_C_LOG_DEBUG("retrying Serial interface reset.");
194194
}
195195

196196
// Done

note.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ enum {
7272

7373
#ifdef NOTE_C_LOW_MEM
7474
#define ERRSTR(x,y) (y)
75+
#define NOTE_C_LOG_DEBUG(msg) do { } while (0)
7576
#else
7677
#define ERRSTR(x,y) (x)
7778
#endif // NOTE_C_LOW_MEM
@@ -384,29 +385,37 @@ void NoteDebugWithLevelLn(uint8_t level, const char *msg);
384385
#define NOTE_C_LOG_FILE_AND_LINE(lvl)
385386
#endif
386387

388+
#ifndef NOTE_C_LOG_ERROR
387389
#define NOTE_C_LOG_ERROR(msg) do { \
388390
NOTE_C_LOG_FILE_AND_LINE(NOTE_C_LOG_LEVEL_ERROR); \
389391
NoteDebugWithLevel(NOTE_C_LOG_LEVEL_ERROR, "[ERROR] "); \
390392
NoteDebugWithLevelLn(NOTE_C_LOG_LEVEL_ERROR, msg); \
391-
} while (0);
393+
} while (0)
394+
#endif
392395

396+
#ifndef NOTE_C_LOG_WARN
393397
#define NOTE_C_LOG_WARN(msg) do { \
394398
NOTE_C_LOG_FILE_AND_LINE(NOTE_C_LOG_LEVEL_WARN); \
395399
NoteDebugWithLevel(NOTE_C_LOG_LEVEL_WARN, "[WARN] "); \
396400
NoteDebugWithLevelLn(NOTE_C_LOG_LEVEL_WARN, msg); \
397-
} while (0);
401+
} while (0)
402+
#endif
398403

404+
#ifndef NOTE_C_LOG_INFO
399405
#define NOTE_C_LOG_INFO(msg) do { \
400406
NOTE_C_LOG_FILE_AND_LINE(NOTE_C_LOG_LEVEL_INFO); \
401407
NoteDebugWithLevel(NOTE_C_LOG_LEVEL_INFO, "[INFO] "); \
402408
NoteDebugWithLevelLn(NOTE_C_LOG_LEVEL_INFO, msg); \
403-
} while (0);
409+
} while (0)
410+
#endif
404411

412+
#ifndef NOTE_C_LOG_DEBUG
405413
#define NOTE_C_LOG_DEBUG(msg) do { \
406414
NOTE_C_LOG_FILE_AND_LINE(NOTE_C_LOG_LEVEL_DEBUG); \
407415
NoteDebugWithLevel(NOTE_C_LOG_LEVEL_DEBUG, "[DEBUG] "); \
408416
NoteDebugWithLevelLn(NOTE_C_LOG_LEVEL_DEBUG, msg); \
409-
} while (0);
417+
} while (0)
418+
#endif
410419

411420
// The default log level
412421
#define NOTE_C_LOG_LEVEL_DEFAULT NOTE_C_LOG_LEVEL_INFO

test/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ endmacro(add_test)
5555

5656
add_test(_crcAdd_test)
5757
add_test(_crcError_test)
58+
add_test(_errDoc_test)
5859
add_test(_i2cChunkedReceive_test)
5960
add_test(_i2cChunkedTransmit_test)
6061
add_test(_i2cNoteChunkedReceive_test)
@@ -75,6 +76,7 @@ add_test(_noteSerialReceive_test)
7576
add_test(_noteSerialReset_test)
7677
add_test(_noteSerialTransmit_test)
7778
add_test(_noteSetActiveInterface_test)
79+
add_test(_noteTransaction_calculateTimeoutMs_test)
7880
add_test(_serialChunkedReceive_test)
7981
add_test(_serialChunkedTransmit_test)
8082
add_test(_serialNoteReset_test)
@@ -168,6 +170,7 @@ add_test(NoteRequestResponseWithRetry_test)
168170
add_test(NoteRequestWithRetry_test)
169171
add_test(NoteReset_test)
170172
add_test(NoteResponseError_test)
173+
add_test(NoteResumeTransactionDebug_test)
171174
add_test(NoteSendToRoute_test)
172175
add_test(NoteSerialHooks_test)
173176
add_test(NoteSetActiveInterface_test)
@@ -194,6 +197,7 @@ add_test(NoteSetSerialNumber_test)
194197
add_test(NoteSetSyncMode_test)
195198
add_test(NoteSetUploadMode_test)
196199
add_test(NoteSleep_test)
200+
add_test(NoteSuspendTransactionDebug_test)
197201
add_test(NoteTemplate_test)
198202
add_test(NoteTime_test)
199203
add_test(NoteTimeSet_test)

test/include/test_static.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#pragma once
22

3+
#include <stdint.h>
4+
35
#include "n_lib.h"
46

57
// If we're building the tests, NOTE_C_STATIC is defined to nothing. This allows
@@ -15,11 +17,14 @@ extern "C" {
1517
char *_crcAdd(char *json, uint16_t seqno);
1618
bool _crcError(char *json, uint16_t shouldBeSeqno);
1719
void _delayIO(void);
20+
J * _errDoc(uint32_t id, const char *errmsg);
1821
const char * _i2cNoteQueryLength(uint32_t * available, uint32_t timeoutMs);
22+
char _j_tolower(char c);
1923
void _noteSetActiveInterface(int interface);
24+
uint32_t _noteTransaction_calculateTimeoutMs(J *req, bool isReq);
25+
unsigned char *_print(const J * const item, Jbool format, Jbool omitempty);
2026
void _setTime(JTIME seconds);
2127
bool _timerExpiredSecs(uint32_t *timer, uint32_t periodSecs);
22-
char _j_tolower(char c);
2328

2429
#ifdef __cplusplus
2530
}

0 commit comments

Comments
 (0)