mirror of
https://github.com/crosspoint-reader/crosspoint-reader.git
synced 2026-08-13 14:21:57 -07:00
601 lines
20 KiB
C++
601 lines
20 KiB
C++
#include <gtest/gtest.h>
|
|
|
|
#include <cstring>
|
|
#include <string>
|
|
|
|
#include "lib/JsonParser/ReleaseJsonParser.h"
|
|
|
|
namespace {
|
|
|
|
const char* kRealisticPretty = R"({
|
|
"url": "https://api.github.com/repos/crosspoint-reader/crosspoint-reader/releases/12345",
|
|
"assets_url": "https://api.github.com/repos/crosspoint-reader/crosspoint-reader/releases/12345/assets",
|
|
"upload_url": "https://uploads.github.com/repos/crosspoint-reader/crosspoint-reader/releases/12345/assets{?name,label}",
|
|
"html_url": "https://github.com/crosspoint-reader/crosspoint-reader/releases/tag/v2.4.1",
|
|
"id": 12345,
|
|
"author": {
|
|
"login": "releasebot",
|
|
"id": 99887766,
|
|
"node_id": "MDQ6VXNlcjk5ODg3NzY2",
|
|
"avatar_url": "https://avatars.githubusercontent.com/u/99887766?v=4",
|
|
"url": "https://api.github.com/users/releasebot",
|
|
"type": "User",
|
|
"site_admin": false
|
|
},
|
|
"node_id": "RE_kwDOAbCdEf4AADBN",
|
|
"tag_name": "v2.4.1",
|
|
"target_commitish": "main",
|
|
"name": "CrossPoint Reader v2.4.1",
|
|
"draft": false,
|
|
"prerelease": false,
|
|
"created_at": "2026-04-28T10:00:00Z",
|
|
"published_at": "2026-04-28T10:30:00Z",
|
|
"assets": [
|
|
{
|
|
"url": "https://api.github.com/repos/crosspoint-reader/crosspoint-reader/releases/assets/100001",
|
|
"id": 100001,
|
|
"node_id": "RA_kwDOAbCdEf4AAGHR",
|
|
"name": "crosspoint-reader-v2.4.1-source.zip",
|
|
"label": null,
|
|
"uploader": {
|
|
"login": "releasebot",
|
|
"id": 99887766,
|
|
"node_id": "MDQ6VXNlcjk5ODg3NzY2",
|
|
"type": "User"
|
|
},
|
|
"content_type": "application/zip",
|
|
"state": "uploaded",
|
|
"size": 2048576,
|
|
"download_count": 42,
|
|
"created_at": "2026-04-28T10:15:00Z",
|
|
"updated_at": "2026-04-28T10:15:30Z",
|
|
"browser_download_url": "https://github.com/crosspoint-reader/crosspoint-reader/releases/download/v2.4.1/crosspoint-reader-v2.4.1-source.zip"
|
|
},
|
|
{
|
|
"url": "https://api.github.com/repos/crosspoint-reader/crosspoint-reader/releases/assets/100002",
|
|
"id": 100002,
|
|
"node_id": "RA_kwDOAbCdEf4AAGHS",
|
|
"name": "firmware.bin",
|
|
"label": "ESP32-C3 Firmware",
|
|
"uploader": {
|
|
"login": "releasebot",
|
|
"id": 99887766,
|
|
"node_id": "MDQ6VXNlcjk5ODg3NzY2",
|
|
"type": "User"
|
|
},
|
|
"content_type": "application/octet-stream",
|
|
"state": "uploaded",
|
|
"size": 1572864,
|
|
"download_count": 187,
|
|
"created_at": "2026-04-28T10:16:00Z",
|
|
"updated_at": "2026-04-28T10:16:45Z",
|
|
"browser_download_url": "https://github.com/crosspoint-reader/crosspoint-reader/releases/download/v2.4.1/firmware.bin"
|
|
},
|
|
{
|
|
"url": "https://api.github.com/repos/crosspoint-reader/crosspoint-reader/releases/assets/100003",
|
|
"id": 100003,
|
|
"node_id": "RA_kwDOAbCdEf4AAGHR",
|
|
"name": "checksums.sha256",
|
|
"label": null,
|
|
"uploader": {
|
|
"login": "releasebot",
|
|
"id": 99887766,
|
|
"node_id": "MDQ6VXNlcjk5ODg3NzY2",
|
|
"type": "User"
|
|
},
|
|
"content_type": "text/plain",
|
|
"state": "uploaded",
|
|
"size": 192,
|
|
"download_count": 15,
|
|
"created_at": "2026-04-28T10:17:00Z",
|
|
"updated_at": "2026-04-28T10:17:10Z",
|
|
"browser_download_url": "https://github.com/crosspoint-reader/crosspoint-reader/releases/download/v2.4.1/checksums.sha256"
|
|
}
|
|
],
|
|
"tarball_url": "https://api.github.com/repos/crosspoint-reader/crosspoint-reader/tarball/v2.4.1",
|
|
"zipball_url": "https://api.github.com/repos/crosspoint-reader/crosspoint-reader/zipball/v2.4.1",
|
|
"body": "## What's Changed\n\n* Fixed orientation crash (#123)\n* Improved EPUB rendering performance\n* Added Serbian translation\n\n**Full Changelog**: https://github.com/crosspoint-reader/crosspoint-reader/compare/v2.4.0...v2.4.1",
|
|
"reactions": {
|
|
"url": "https://api.github.com/repos/crosspoint-reader/crosspoint-reader/releases/12345/reactions",
|
|
"total_count": 5,
|
|
"+1": 3,
|
|
"-1": 0,
|
|
"laugh": 1,
|
|
"hooray": 1,
|
|
"confused": 0,
|
|
"heart": 0,
|
|
"rocket": 0,
|
|
"eyes": 0
|
|
}
|
|
})";
|
|
|
|
const char* kRealisticMinified =
|
|
R"({"url":"https://api.github.com/repos/crosspoint-reader/crosspoint-reader/releases/12345","assets_url":"https://api.github.com/repos/crosspoint-reader/crosspoint-reader/releases/12345/assets","id":12345,"author":{"login":"releasebot","id":99887766,"node_id":"MDQ6VXNlcjk5ODg3NzY2","type":"User","site_admin":false},"tag_name":"v2.4.1","target_commitish":"main","name":"CrossPoint Reader v2.4.1","draft":false,"prerelease":false,"assets":[{"url":"https://api.github.com/repos/crosspoint-reader/crosspoint-reader/releases/assets/100001","id":100001,"name":"crosspoint-reader-v2.4.1-source.zip","uploader":{"login":"releasebot","id":99887766},"content_type":"application/zip","state":"uploaded","size":2048576,"download_count":42,"browser_download_url":"https://github.com/crosspoint-reader/crosspoint-reader/releases/download/v2.4.1/crosspoint-reader-v2.4.1-source.zip"},{"url":"https://api.github.com/repos/crosspoint-reader/crosspoint-reader/releases/assets/100002","id":100002,"name":"firmware.bin","uploader":{"login":"releasebot","id":99887766},"content_type":"application/octet-stream","state":"uploaded","size":1572864,"download_count":187,"browser_download_url":"https://github.com/crosspoint-reader/crosspoint-reader/releases/download/v2.4.1/firmware.bin"},{"url":"https://api.github.com/repos/crosspoint-reader/crosspoint-reader/releases/assets/100003","id":100003,"name":"checksums.sha256","uploader":{"login":"releasebot","id":99887766},"content_type":"text/plain","state":"uploaded","size":192,"download_count":15,"browser_download_url":"https://github.com/crosspoint-reader/crosspoint-reader/releases/download/v2.4.1/checksums.sha256"}],"body":"## What's Changed\n\n* Fixed orientation crash","reactions":{"url":"https://api.github.com/repos/crosspoint-reader/crosspoint-reader/releases/12345/reactions","total_count":5,"+1":3}})";
|
|
|
|
void feedChunked(ReleaseJsonParser& p, const char* json, size_t chunkSize) {
|
|
size_t len = strlen(json);
|
|
for (size_t off = 0; off < len; off += chunkSize) {
|
|
size_t n = len - off < chunkSize ? len - off : chunkSize;
|
|
p.feed(json + off, n);
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
TEST(ReleaseJsonParser, RealisticPrettyPrinted) {
|
|
ReleaseJsonParser p;
|
|
p.feed(kRealisticPretty, strlen(kRealisticPretty));
|
|
|
|
EXPECT_TRUE(p.foundTag());
|
|
EXPECT_TRUE(p.foundFirmware());
|
|
EXPECT_STREQ(p.getTagName(), "v2.4.1");
|
|
EXPECT_STREQ(p.getFirmwareUrl(),
|
|
"https://github.com/crosspoint-reader/crosspoint-reader/releases/download/v2.4.1/firmware.bin");
|
|
EXPECT_EQ(p.getFirmwareSize(), 1572864u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, RealisticMinified) {
|
|
ReleaseJsonParser p;
|
|
p.feed(kRealisticMinified, strlen(kRealisticMinified));
|
|
|
|
EXPECT_TRUE(p.foundTag());
|
|
EXPECT_TRUE(p.foundFirmware());
|
|
EXPECT_STREQ(p.getTagName(), "v2.4.1");
|
|
EXPECT_STREQ(p.getFirmwareUrl(),
|
|
"https://github.com/crosspoint-reader/crosspoint-reader/releases/download/v2.4.1/firmware.bin");
|
|
EXPECT_EQ(p.getFirmwareSize(), 1572864u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, PrettyAndMinifiedAgree) {
|
|
ReleaseJsonParser pretty;
|
|
pretty.feed(kRealisticPretty, strlen(kRealisticPretty));
|
|
|
|
ReleaseJsonParser minified;
|
|
minified.feed(kRealisticMinified, strlen(kRealisticMinified));
|
|
|
|
ASSERT_TRUE(pretty.foundTag());
|
|
ASSERT_TRUE(pretty.foundFirmware());
|
|
ASSERT_TRUE(minified.foundTag());
|
|
ASSERT_TRUE(minified.foundFirmware());
|
|
|
|
EXPECT_STREQ(pretty.getTagName(), minified.getTagName());
|
|
EXPECT_STREQ(pretty.getFirmwareUrl(), minified.getFirmwareUrl());
|
|
EXPECT_EQ(pretty.getFirmwareSize(), minified.getFirmwareSize());
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, FirmwareNotFirstAsset) {
|
|
const char* json = R"({
|
|
"tag_name": "v1.0.0",
|
|
"assets": [
|
|
{"name": "source.tar.gz", "browser_download_url": "https://example.com/src.tar.gz", "size": 500000},
|
|
{"name": "docs.pdf", "browser_download_url": "https://example.com/docs.pdf", "size": 120000},
|
|
{"name": "firmware.bin", "browser_download_url": "https://example.com/firmware.bin", "size": 987654},
|
|
{"name": "checksums.txt", "browser_download_url": "https://example.com/checksums.txt", "size": 256}
|
|
]
|
|
})";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_TRUE(p.foundTag());
|
|
EXPECT_TRUE(p.foundFirmware());
|
|
EXPECT_STREQ(p.getTagName(), "v1.0.0");
|
|
EXPECT_STREQ(p.getFirmwareUrl(), "https://example.com/firmware.bin");
|
|
EXPECT_EQ(p.getFirmwareSize(), 987654u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, FieldOrderUrlBeforeName) {
|
|
const char* json = R"({
|
|
"tag_name": "v3.0",
|
|
"assets": [{
|
|
"browser_download_url": "https://example.com/fw.bin",
|
|
"name": "firmware.bin",
|
|
"size": 2222
|
|
}]
|
|
})";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_TRUE(p.foundFirmware());
|
|
EXPECT_STREQ(p.getFirmwareUrl(), "https://example.com/fw.bin");
|
|
EXPECT_EQ(p.getFirmwareSize(), 2222u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, FieldOrderSizeBeforeUrl) {
|
|
const char* json = R"({
|
|
"tag_name": "v3.1",
|
|
"assets": [{
|
|
"size": 3333,
|
|
"browser_download_url": "https://example.com/fw2.bin",
|
|
"name": "firmware.bin"
|
|
}]
|
|
})";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_TRUE(p.foundFirmware());
|
|
EXPECT_STREQ(p.getFirmwareUrl(), "https://example.com/fw2.bin");
|
|
EXPECT_EQ(p.getFirmwareSize(), 3333u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, FieldOrderNameFirst) {
|
|
const char* json = R"({
|
|
"tag_name": "v3.2",
|
|
"assets": [{
|
|
"name": "firmware.bin",
|
|
"size": 4444,
|
|
"browser_download_url": "https://example.com/fw3.bin"
|
|
}]
|
|
})";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_TRUE(p.foundFirmware());
|
|
EXPECT_STREQ(p.getFirmwareUrl(), "https://example.com/fw3.bin");
|
|
EXPECT_EQ(p.getFirmwareSize(), 4444u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, AssetsBeforeTagName) {
|
|
// tag_name appears after assets in the JSON
|
|
const char* json = R"({
|
|
"name": "Release",
|
|
"assets": [{
|
|
"name": "firmware.bin",
|
|
"browser_download_url": "https://example.com/fw.bin",
|
|
"size": 5555
|
|
}],
|
|
"tag_name": "v4.0"
|
|
})";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_TRUE(p.foundTag());
|
|
EXPECT_TRUE(p.foundFirmware());
|
|
EXPECT_STREQ(p.getTagName(), "v4.0");
|
|
EXPECT_STREQ(p.getFirmwareUrl(), "https://example.com/fw.bin");
|
|
EXPECT_EQ(p.getFirmwareSize(), 5555u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, ChunkedFeedingSmallChunks) {
|
|
ReleaseJsonParser p;
|
|
feedChunked(p, kRealisticPretty, 64);
|
|
|
|
EXPECT_TRUE(p.foundTag());
|
|
EXPECT_TRUE(p.foundFirmware());
|
|
EXPECT_STREQ(p.getTagName(), "v2.4.1");
|
|
EXPECT_STREQ(p.getFirmwareUrl(),
|
|
"https://github.com/crosspoint-reader/crosspoint-reader/releases/download/v2.4.1/firmware.bin");
|
|
EXPECT_EQ(p.getFirmwareSize(), 1572864u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, ChunkedFeedingByteByByte) {
|
|
ReleaseJsonParser p;
|
|
feedChunked(p, kRealisticMinified, 1);
|
|
|
|
EXPECT_TRUE(p.foundTag());
|
|
EXPECT_TRUE(p.foundFirmware());
|
|
EXPECT_STREQ(p.getTagName(), "v2.4.1");
|
|
EXPECT_EQ(p.getFirmwareSize(), 1572864u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, ChunkedFeedingVariousChunkSizes) {
|
|
for (size_t chunkSize : {3u, 7u, 13u, 31u, 97u, 128u, 256u, 512u, 1024u}) {
|
|
ReleaseJsonParser p;
|
|
feedChunked(p, kRealisticPretty, chunkSize);
|
|
|
|
EXPECT_TRUE(p.foundTag()) << "chunkSize=" << chunkSize;
|
|
EXPECT_TRUE(p.foundFirmware()) << "chunkSize=" << chunkSize;
|
|
EXPECT_STREQ(p.getTagName(), "v2.4.1") << "chunkSize=" << chunkSize;
|
|
EXPECT_STREQ(p.getFirmwareUrl(),
|
|
"https://github.com/crosspoint-reader/crosspoint-reader/releases/download/v2.4.1/firmware.bin")
|
|
<< "chunkSize=" << chunkSize;
|
|
EXPECT_EQ(p.getFirmwareSize(), 1572864u) << "chunkSize=" << chunkSize;
|
|
}
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, MissingTagName) {
|
|
const char* json = R"({
|
|
"name": "Some Release",
|
|
"draft": false,
|
|
"assets": [{
|
|
"name": "firmware.bin",
|
|
"browser_download_url": "https://example.com/fw.bin",
|
|
"size": 1000
|
|
}]
|
|
})";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_FALSE(p.foundTag());
|
|
EXPECT_TRUE(p.foundFirmware());
|
|
EXPECT_STREQ(p.getTagName(), "");
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, MissingFirmwareBinAsset) {
|
|
const char* json = R"({
|
|
"tag_name": "v1.0.0",
|
|
"assets": [
|
|
{"name": "source.zip", "browser_download_url": "https://example.com/src.zip", "size": 1000},
|
|
{"name": "docs.tar.gz", "browser_download_url": "https://example.com/docs.tar.gz", "size": 2000}
|
|
]
|
|
})";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_TRUE(p.foundTag());
|
|
EXPECT_FALSE(p.foundFirmware());
|
|
EXPECT_STREQ(p.getTagName(), "v1.0.0");
|
|
EXPECT_STREQ(p.getFirmwareUrl(), "");
|
|
EXPECT_EQ(p.getFirmwareSize(), 0u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, EmptyAssetsArray) {
|
|
const char* json = R"({"tag_name": "v1.0.0", "assets": []})";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_TRUE(p.foundTag());
|
|
EXPECT_FALSE(p.foundFirmware());
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, NoAssetsKey) {
|
|
const char* json = R"({"tag_name": "v1.0.0", "name": "Release"})";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_TRUE(p.foundTag());
|
|
EXPECT_FALSE(p.foundFirmware());
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, TruncatedBeforeTagValue) {
|
|
const char* json = R"({"tag_name": )";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_FALSE(p.foundTag());
|
|
EXPECT_FALSE(p.foundFirmware());
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, TruncatedInsideTagValue) {
|
|
const char* json = R"({"tag_name": "v2.4)";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_FALSE(p.foundTag());
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, TruncatedInsideAssetsArray) {
|
|
const char* json = R"({"tag_name": "v2.4.1", "assets": [{"name": "firm)";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_TRUE(p.foundTag());
|
|
EXPECT_STREQ(p.getTagName(), "v2.4.1");
|
|
EXPECT_FALSE(p.foundFirmware());
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, TruncatedAfterFirmwareName) {
|
|
// Found the name but connection dropped before URL/size
|
|
const char* json = R"({"tag_name":"v1.0","assets":[{"name":"firmware.bin","browser_dow)";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_TRUE(p.foundTag());
|
|
EXPECT_FALSE(p.foundFirmware());
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, TruncatedRealisticJson) {
|
|
std::string full(kRealisticPretty);
|
|
for (size_t cutPoint : {10u, 50u, 100u, 200u, 500u, 1000u, 1500u, 2000u}) {
|
|
if (cutPoint >= full.size()) continue;
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(full.c_str(), cutPoint);
|
|
(void)p.foundTag();
|
|
(void)p.foundFirmware();
|
|
}
|
|
SUCCEED();
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, NestedObjectsInAsset) {
|
|
// Asset with deeply nested "uploader" object -- should not confuse depth tracking
|
|
const char* json = R"({
|
|
"tag_name": "v5.0",
|
|
"assets": [{
|
|
"name": "firmware.bin",
|
|
"uploader": {
|
|
"login": "bot",
|
|
"id": 42,
|
|
"permissions": {"admin": false, "push": true, "pull": true}
|
|
},
|
|
"browser_download_url": "https://example.com/fw5.bin",
|
|
"size": 8888
|
|
}]
|
|
})";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_TRUE(p.foundFirmware());
|
|
EXPECT_STREQ(p.getFirmwareUrl(), "https://example.com/fw5.bin");
|
|
EXPECT_EQ(p.getFirmwareSize(), 8888u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, NestedObjectsAtTopLevel) {
|
|
// Multiple nested objects at the top level before/after tag_name and assets
|
|
const char* json = R"({
|
|
"author": {"login": "dev", "id": 1, "nested": {"deep": true}},
|
|
"tag_name": "v6.0",
|
|
"reactions": {"url": "https://reactions", "total_count": 0, "+1": 0},
|
|
"assets": [{"name": "firmware.bin", "browser_download_url": "https://fw6", "size": 1111}],
|
|
"mentions_count": 3
|
|
})";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_TRUE(p.foundTag());
|
|
EXPECT_TRUE(p.foundFirmware());
|
|
EXPECT_STREQ(p.getTagName(), "v6.0");
|
|
EXPECT_EQ(p.getFirmwareSize(), 1111u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, ArraysAtTopLevel) {
|
|
// A non-assets array at the top level should not interfere
|
|
const char* json = R"({
|
|
"tag_name": "v7.0",
|
|
"labels": ["release", "stable"],
|
|
"assets": [{"name": "firmware.bin", "browser_download_url": "https://fw7", "size": 7070}]
|
|
})";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_TRUE(p.foundTag());
|
|
EXPECT_TRUE(p.foundFirmware());
|
|
EXPECT_STREQ(p.getTagName(), "v7.0");
|
|
EXPECT_EQ(p.getFirmwareSize(), 7070u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, ResetAndReuse) {
|
|
ReleaseJsonParser p;
|
|
|
|
const char* json1 =
|
|
R"({"tag_name":"v1.0","assets":[{"name":"firmware.bin","browser_download_url":"https://a","size":1}]})";
|
|
p.feed(json1, strlen(json1));
|
|
EXPECT_TRUE(p.foundTag());
|
|
EXPECT_STREQ(p.getTagName(), "v1.0");
|
|
EXPECT_STREQ(p.getFirmwareUrl(), "https://a");
|
|
EXPECT_EQ(p.getFirmwareSize(), 1u);
|
|
|
|
p.reset();
|
|
|
|
const char* json2 =
|
|
R"({"tag_name":"v2.0","assets":[{"name":"firmware.bin","browser_download_url":"https://b","size":2}]})";
|
|
p.feed(json2, strlen(json2));
|
|
EXPECT_TRUE(p.foundTag());
|
|
EXPECT_STREQ(p.getTagName(), "v2.0");
|
|
EXPECT_STREQ(p.getFirmwareUrl(), "https://b");
|
|
EXPECT_EQ(p.getFirmwareSize(), 2u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, ResetClearsState) {
|
|
ReleaseJsonParser p;
|
|
|
|
const char* json =
|
|
R"({"tag_name":"v1.0","assets":[{"name":"firmware.bin","browser_download_url":"https://a","size":100}]})";
|
|
p.feed(json, strlen(json));
|
|
EXPECT_TRUE(p.foundTag());
|
|
EXPECT_TRUE(p.foundFirmware());
|
|
|
|
p.reset();
|
|
|
|
EXPECT_FALSE(p.foundTag());
|
|
EXPECT_FALSE(p.foundFirmware());
|
|
EXPECT_STREQ(p.getTagName(), "");
|
|
EXPECT_STREQ(p.getFirmwareUrl(), "");
|
|
EXPECT_EQ(p.getFirmwareSize(), 0u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, PartialAssetNameMatch) {
|
|
// "firmware.bin.bak" should NOT match "firmware.bin"
|
|
const char* json = R"({
|
|
"tag_name": "v1.0",
|
|
"assets": [
|
|
{"name": "firmware.bin.bak", "browser_download_url": "https://bak", "size": 100},
|
|
{"name": "firmware.bin.old", "browser_download_url": "https://old", "size": 200}
|
|
]
|
|
})";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_TRUE(p.foundTag());
|
|
EXPECT_FALSE(p.foundFirmware());
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, FirmwareBinExactMatch) {
|
|
// Only exact "firmware.bin" matches, not similar names
|
|
const char* json = R"({
|
|
"tag_name": "v1.0",
|
|
"assets": [
|
|
{"name": "FIRMWARE.BIN", "browser_download_url": "https://upper", "size": 100},
|
|
{"name": "firmware.bin", "browser_download_url": "https://exact", "size": 200},
|
|
{"name": "firmware.bin2", "browser_download_url": "https://suffix", "size": 300}
|
|
]
|
|
})";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_TRUE(p.foundFirmware());
|
|
EXPECT_STREQ(p.getFirmwareUrl(), "https://exact");
|
|
EXPECT_EQ(p.getFirmwareSize(), 200u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, LargeSize) {
|
|
// 16MB firmware (maximum flash size)
|
|
const char* json =
|
|
R"({"tag_name":"v1.0","assets":[{"name":"firmware.bin","browser_download_url":"https://fw","size":16777216}]})";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_EQ(p.getFirmwareSize(), 16777216u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, SizeZero) {
|
|
const char* json =
|
|
R"({"tag_name":"v1.0","assets":[{"name":"firmware.bin","browser_download_url":"https://fw","size":0}]})";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_TRUE(p.foundFirmware());
|
|
EXPECT_EQ(p.getFirmwareSize(), 0u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, MinimalValidJson) {
|
|
const char* json = R"({"tag_name":"v0","assets":[{"name":"firmware.bin","browser_download_url":"u","size":1}]})";
|
|
|
|
ReleaseJsonParser p;
|
|
p.feed(json, strlen(json));
|
|
|
|
EXPECT_TRUE(p.foundTag());
|
|
EXPECT_TRUE(p.foundFirmware());
|
|
EXPECT_STREQ(p.getTagName(), "v0");
|
|
EXPECT_STREQ(p.getFirmwareUrl(), "u");
|
|
EXPECT_EQ(p.getFirmwareSize(), 1u);
|
|
}
|
|
|
|
TEST(ReleaseJsonParser, ChunkedRealisticEveryBoundary) {
|
|
// Two-chunk split at every byte boundary on a compact JSON
|
|
const char* json =
|
|
R"({"tag_name":"v2.0","assets":[{"name":"firmware.bin","browser_download_url":"https://example.com/fw","size":9999}]})";
|
|
size_t len = strlen(json);
|
|
|
|
for (size_t split = 0; split <= len; ++split) {
|
|
ReleaseJsonParser p;
|
|
if (split > 0) p.feed(json, split);
|
|
if (split < len) p.feed(json + split, len - split);
|
|
|
|
EXPECT_TRUE(p.foundTag()) << "split=" << split;
|
|
EXPECT_TRUE(p.foundFirmware()) << "split=" << split;
|
|
EXPECT_STREQ(p.getTagName(), "v2.0") << "split=" << split;
|
|
EXPECT_STREQ(p.getFirmwareUrl(), "https://example.com/fw") << "split=" << split;
|
|
EXPECT_EQ(p.getFirmwareSize(), 9999u) << "split=" << split;
|
|
}
|
|
}
|