Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/notecard-binary-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,14 @@ jobs:
echo "build flags $PLATFORMIO_BUILD_FLAGS"
cd $GITHUB_WORKSPACE/$PIO_PROJECT_DIR

# Enable Notecard USB trace output.
printf '{"req":"card.trace","mode":"usb","trace":"req,comm,sync,mem"}\n' > "$RESERVATION_DIR/notecard_usb"

# Stream Notecard USB output to trace.log in the background.
socat -u GOPEN:"$RESERVATION_DIR/notecard_usb",rawer - >> "$GITHUB_WORKSPACE/trace.log" &
TRACE_PID=$!
echo "Notecard trace capture started (PID: $TRACE_PID)."

# Run the tests. It's important that we provided --no-reset here. If
# we don't, PlatformIO tries to fiddle with DTR and RTS, and that
# causes an exception because the serial port for the Swan isn't a
Expand All @@ -309,6 +317,7 @@ jobs:
--json-output-path test.json \
--junit-output-path test.xml

kill $TRACE_PID 2>/dev/null
kill $PID 2>/dev/null

- name: Publish test report
Expand All @@ -321,6 +330,22 @@ jobs:
check_name: Notecard Binary HIL Tests
require_tests: true

- name: Upload trace log
uses: actions/upload-artifact@v4
if: always()
with:
name: notecard-trace
path: trace.log
if-no-files-found: ignore

- name: Upload MD5 server log
uses: actions/upload-artifact@v4
if: always()
with:
name: md5srv-log
path: md5srv.log
if-no-files-found: ignore

- name: Cleanup Notehub proxy route
if: always()
run: |
Expand Down
22 changes: 20 additions & 2 deletions test/hitl/scripts/md5srv.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@ def query_data(self):

@cached_property
def post_data(self):
transfer_encoding = self.headers.get("Transfer-Encoding", "")
if "chunked" in transfer_encoding.lower():
data = b""
while True:
chunk_size = int(self.rfile.readline().strip(), 16)
if chunk_size == 0:
break
data += self.rfile.read(chunk_size)
self.rfile.read(2) # consume trailing \r\n after chunk data
return data
content_length = int(self.headers.get("Content-Length", 0))
return self.rfile.read(content_length)

Expand Down Expand Up @@ -107,15 +117,23 @@ def send_status(self,
reply_body = reply_body + '\n'
self.wfile.write(reply_body.encode('utf-8'))

def log_request_headers(self):
content_length = self.headers.get("Content-Length", "<absent>")
transfer_encoding = self.headers.get("Transfer-Encoding", "<absent>")
content_type = self.headers.get("Content-Type", "<absent>")
log(f"{self.command} {self.path} | Content-Length: {content_length} | Transfer-Encoding: {transfer_encoding} | Content-Type: {content_type}")

def do(self, handler):
""" Handle a request. If an exception is thrown, raises an internal server error. """
try:
# print(self.dump_request())
self.validate_token()
handler()
except HTTPException as e:
self.log_request_headers()
log(f"HTTP {e.status_code}: {e.message}" + (f" | {e.detail}" if e.detail else ""))
self.send_status(e.status_code, e.message, e.detail)
except Exception as e:
self.log_request_headers()
traceback.print_exc()
self.send_status(500, "Internal server error.", str(e))

Expand Down Expand Up @@ -207,7 +225,7 @@ def write_note(self):
self._write_file(name, chunk, length, payload, md5)

def write_file(self):
length = int(self.headers['Content-Length'])
length = int(self.headers['Content-Length'] or len(self.post_data))
if not length:
raise HTTPException(400, "Request body is empty.")
chunk = self.query_data.get("chunk", None)
Expand Down
6 changes: 4 additions & 2 deletions test/src/_cobsDecode_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ SCENARIO("_cobsDecode")
0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x02,
0xFF};
0xFF
};

WHEN("The array is COBS-decoded") {
const uint32_t decodedLen = _cobsDecode(encoded, sizeof(encoded), eop, decoded);
Expand Down Expand Up @@ -237,7 +238,8 @@ SCENARIO("_cobsDecode")
0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8,
0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0,
0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF};
0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
};
REQUIRE(decodedLen == sizeof(expectedDecoded));
CHECK(memcmp(decoded, expectedDecoded, sizeof(expectedDecoded)) == 0);
}
Expand Down
6 changes: 4 additions & 2 deletions test/src/_cobsEncode_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ SCENARIO("_cobsEncode")
0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8,
0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0,
0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF};
0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
};

WHEN("The array is COBS-encoded") {
const uint32_t encodedLen = _cobsEncode(unencoded, 255, eop, encoded);
Expand Down Expand Up @@ -248,7 +249,8 @@ SCENARIO("_cobsEncode")
0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x02,
0xFF};
0xFF
};
REQUIRE(encodedLen == sizeof(expectedEncoded));
CHECK(memcmp(encoded, expectedEncoded, sizeof(expectedEncoded)) == 0);
}
Expand Down
6 changes: 4 additions & 2 deletions test/src/_cobsEncodedLength_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ SCENARIO("_cobsEncodedLength")
0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8,
0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0,
0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF};
0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
};

WHEN("The array is evaluated for its COBS-encoded length") {
const uint32_t encodedLen = _cobsEncodedLength(unencoded, sizeof(unencoded));
Expand Down Expand Up @@ -205,7 +206,8 @@ SCENARIO("_cobsEncodedLength")
0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8,
0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0,
0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF};
0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
};
CHECK(memcmp(unencoded, original, sizeof(original)) == 0);
}
}
Expand Down
Loading