Files
MeshCore/test/fixtures/companion_john/test_john.cpp
T

95 lines
4.6 KiB
C++

#include <Arduino.h>
#include <helpers/CompanionJohn.h>
#include <helpers/bible/JohnData.generated.h>
#include <cassert>
#include <cstdio>
#include <string>
#include <vector>
using namespace mesh::bible;
int main(int argc, char**) {
Reference ref = {};
for (const char* cmd : {"get John 3:16", " GET\tJoHn 3:16 \t", "get john 03:16"}) {
assert(parse(cmd, ref) == ParseResult::Valid && ref.chapter == 3 && ref.verse == 16);
}
for (const char* cmd : {"get John", "get John 0:1", "get John 22:1",
"get John 1:52", "get John 3:0", "get John -3:16", "get John 3:16-18",
"get John 3:16 junk", "get John 9999999999:1", "get John 1:9999999999",
"get John 3:", "get John 3:16\x1b", "get John 3 :16", "get John :16"}) {
assert(parse(cmd, ref) == ParseResult::Invalid);
}
for (const char* cmd : {"get name", "forget John 3:16", "get johnny 3:16",
"get 1 John 3:16", "getJohn 3:16", "", "get J", "get", "g"}) {
assert(parse(cmd, ref) == ParseResult::NoMatch);
Stream output;
assert(!mesh::handleJohnCommand(cmd, output) && output.text.empty());
}
assert(parse(nullptr, ref) == ParseResult::NoMatch);
const Corpus& corpus = generated::johnCorpus;
struct Guarded { uint32_t pre; char scratch[kBlockSize]; uint32_t post; } buf = {};
buf.pre = 0x11223344; buf.post = 0xaabbccdd;
unsigned count = 0;
for (uint8_t chapter = 1; chapter <= 21; ++chapter) {
for (uint8_t verse = 1; verse <= kChapterVerses[chapter - 1]; ++verse) {
const char* text;
assert(lookup(corpus, {chapter, verse}, buf.scratch, kBlockSize, text) == LookupResult::Found);
assert(buf.pre == 0x11223344 && buf.post == 0xaabbccdd);
char cmd[32];
snprintf(cmd, sizeof(cmd), "get John %u:%u", chapter, verse);
Stream output;
assert(mesh::handleJohnCommand(cmd, output));
const std::string expected = "\r\n" + std::string(text) + "\r\n";
assert(output.text.find(expected) != std::string::npos);
for (const unsigned char* c = reinterpret_cast<const unsigned char*>(text); *c; ++c)
assert(*c >= 32 && *c < 127);
// A machine-readable dump lets Python compare every decoded byte to
// the independently ASCII-normalized pinned plaintext source.
if (argc > 1) std::printf("%u:%u\t%s\n", chapter, verse, text);
++count;
}
}
assert(count == 879);
const char* text;
assert(lookup(corpus, {22, 1}, buf.scratch, kBlockSize, text) == LookupResult::Invalid);
assert(lookup(corpus, {1, 1}, buf.scratch, kBlockSize - 1, text) == LookupResult::Corrupt);
Corpus bad = corpus;
bad.data_size = 0;
assert(lookup(bad, {1, 1}, buf.scratch, kBlockSize, text) == LookupResult::Corrupt);
bad = corpus; bad.block_count = 0;
assert(lookup(bad, {1, 1}, buf.scratch, kBlockSize, text) == LookupResult::Corrupt);
bad = corpus; bad.verse_count = 878;
assert(lookup(bad, {1, 1}, buf.scratch, kBlockSize, text) == LookupResult::Corrupt);
assert(lookup(corpus, {1, 1}, nullptr, kBlockSize, text) == LookupResult::Corrupt);
// One-byte stored DEFLATE block: distinguish an absent verse marker from
// damaged text without a terminator, and never return an unsafe pointer.
uint8_t stored[] = {0x01, 0x01, 0x00, 0xfe, 0xff, 0x00};
const BlockIndex stored_index = {0, sizeof(stored), 1, 0};
bad = corpus; bad.data = stored; bad.data_size = sizeof(stored);
bad.blocks = &stored_index; bad.block_count = 1;
assert(lookup(bad, {1, 1}, buf.scratch, kBlockSize, text) == LookupResult::Missing);
assert(text == nullptr);
stored[5] = 'x';
assert(lookup(bad, {1, 1}, buf.scratch, kBlockSize, text) == LookupResult::Corrupt);
assert(text == nullptr);
assert(lookup(bad, {1, 2}, buf.scratch, kBlockSize, text) == LookupResult::Corrupt);
std::vector<BlockIndex> blocks(corpus.blocks, corpus.blocks + corpus.block_count);
bad = corpus; bad.blocks = blocks.data();
for (int mutation = 0; mutation != 5; ++mutation) {
blocks[0] = corpus.blocks[0];
switch (mutation) {
case 0: blocks[0].plain = kBlockSize + 1; break;
case 1: blocks[0].packed--; break;
case 2: blocks[0].packed++; break; // Trailing bytes are rejected.
case 3: blocks[0].offset = UINT32_MAX; break;
case 4: blocks[0].first_verse = 1; break;
}
assert(lookup(bad, {1, 1}, buf.scratch, kBlockSize, text) == LookupResult::Corrupt);
assert(text == nullptr && buf.pre == 0x11223344 && buf.post == 0xaabbccdd);
}
Stream invalid;
assert(mesh::handleJohnCommand("get John 3:99", invalid));
assert(invalid.text.find("ERROR") != std::string::npos);
if (argc == 1) std::puts("All 879 verses, terminal output, parser and corruption checks passed");
}