/* * Copyright 2017-2023, Andrew Lindesay * Distributed under the terms of the MIT License. */ #include "JsonEndToEndTest.h" #include #include #include #include #include #include "ChecksumJsonEventListener.h" #include "FakeJsonDataGenerator.h" #include "JsonSamples.h" using namespace BPrivate; static const size_t kHighVolumeItemCount = 10000; static const uint32 kChecksumLimit = 100000; JsonEndToEndTest::JsonEndToEndTest() { } JsonEndToEndTest::~JsonEndToEndTest() { } /*! Just here so it is possible to extract timings for the data generation cost. */ void JsonEndToEndTest::TestHighVolumeStringSampleGenerationOnly() { FakeJsonStreamDataIO* inputData = new FakeJsonStringStreamDataIO(kHighVolumeItemCount, kChecksumLimit); char c; while (inputData->Read(&c, 1) == 1) { // do nothing } } /*! Just here so it is possible to extract timings for the data generation cost. */ void JsonEndToEndTest::TestHighVolumeNumberSampleGenerationOnly() { FakeJsonStreamDataIO* inputData = new FakeJsonNumberStreamDataIO(kHighVolumeItemCount, kChecksumLimit); char c; while (inputData->Read(&c, 1) == 1) { // do nothing } } void JsonEndToEndTest::TestHighVolumeStringParsing() { FakeJsonStreamDataIO* inputData = new FakeJsonStringStreamDataIO(kHighVolumeItemCount, kChecksumLimit); ChecksumJsonEventListener* listener = new ChecksumJsonEventListener(kChecksumLimit); // ---------------------- BPrivate::BJson::Parse(inputData, listener); // ---------------------- CPPUNIT_ASSERT_EQUAL(B_OK, listener->Error()); CPPUNIT_ASSERT_EQUAL(inputData->Checksum(), listener->Checksum()); } void JsonEndToEndTest::TestHighVolumeNumberParsing() { FakeJsonStreamDataIO* inputData = new FakeJsonNumberStreamDataIO(kHighVolumeItemCount, kChecksumLimit); ChecksumJsonEventListener* listener = new ChecksumJsonEventListener(kChecksumLimit); // ---------------------- BPrivate::BJson::Parse(inputData, listener); // ---------------------- CPPUNIT_ASSERT_EQUAL(B_OK, listener->Error()); CPPUNIT_ASSERT_EQUAL(inputData->Checksum(), listener->Checksum()); } void JsonEndToEndTest::TestParseAndWrite(const char* input, const char* expectedOutput) { BDataIO* inputData = new BMemoryIO(input, strlen(input)); ObjectDeleter inputDataDeleter(inputData); BMallocIO* outputData = new BMallocIO(); ObjectDeleter outputDataDeleter(outputData); BPrivate::BJsonTextWriter* listener = new BJsonTextWriter(outputData); ObjectDeleter listenerDeleter(listener); // ---------------------- BPrivate::BJson::Parse(inputData, listener); // ---------------------- CPPUNIT_ASSERT_EQUAL(B_OK, listener->ErrorStatus()); fprintf(stderr, "in >%s<\n", input); fprintf(stderr, "expected out >%s<\n", expectedOutput); fprintf(stderr, "actual out >%s<\n", (char*)outputData->Buffer()); CPPUNIT_ASSERT_MESSAGE("expected did no equal actual output", 0 == strncmp(expectedOutput, (char*)outputData->Buffer(), strlen(expectedOutput))); } void JsonEndToEndTest::TestNullA() { TestParseAndWrite(JSON_SAMPLE_NULL_A_IN, JSON_SAMPLE_NULL_A_EXPECTED_OUT); } void JsonEndToEndTest::TestTrueA() { TestParseAndWrite(JSON_SAMPLE_TRUE_A_IN, JSON_SAMPLE_TRUE_A_EXPECTED_OUT); } void JsonEndToEndTest::TestFalseA() { TestParseAndWrite(JSON_SAMPLE_FALSE_A_IN, JSON_SAMPLE_FALSE_A_EXPECTED_OUT); } void JsonEndToEndTest::TestNumberA() { TestParseAndWrite(JSON_SAMPLE_NUMBER_A_IN, JSON_SAMPLE_NUMBER_A_EXPECTED_OUT); } void JsonEndToEndTest::TestStringA() { TestParseAndWrite(JSON_SAMPLE_STRING_A_IN, JSON_SAMPLE_STRING_A_EXPECTED_OUT); } void JsonEndToEndTest::TestStringB() { TestParseAndWrite(JSON_SAMPLE_STRING_B_IN, JSON_SAMPLE_STRING_B_EXPECTED_OUT); } /* In this test, there are some UTF-8 characters. */ void JsonEndToEndTest::TestStringA2() { TestParseAndWrite(JSON_SAMPLE_STRING_A2_IN, JSON_SAMPLE_STRING_A_EXPECTED_OUT); } void JsonEndToEndTest::TestArrayA() { TestParseAndWrite(JSON_SAMPLE_ARRAY_A_IN, JSON_SAMPLE_ARRAY_A_EXPECTED_OUT); } void JsonEndToEndTest::TestArrayB() { TestParseAndWrite(JSON_SAMPLE_ARRAY_B_IN, JSON_SAMPLE_ARRAY_B_EXPECTED_OUT); } void JsonEndToEndTest::TestObjectA() { TestParseAndWrite(JSON_SAMPLE_OBJECT_A_IN, JSON_SAMPLE_OBJECT_A_EXPECTED_OUT); } /*! This method will test an element being unterminated; such an object that is missing the terminating "}" symbol or a string that has no closing quote. This is tested here because the writer */ void JsonEndToEndTest::TestUnterminated(const char *input) { BDataIO* inputData = new BMemoryIO(input, strlen(input)); ObjectDeleter inputDataDeleter(inputData); BMallocIO* outputData = new BMallocIO(); ObjectDeleter outputDataDeleter(outputData); BPrivate::BJsonTextWriter* listener = new BJsonTextWriter(outputData); ObjectDeleter listenerDeleter(listener); // ---------------------- BPrivate::BJson::Parse(inputData, listener); // ---------------------- CPPUNIT_ASSERT_EQUAL(B_BAD_DATA, listener->ErrorStatus()); } void JsonEndToEndTest::TestStringUnterminated() { TestUnterminated(JSON_SAMPLE_BROKEN_UNTERMINATED_STRING); } void JsonEndToEndTest::TestArrayUnterminated() { TestUnterminated(JSON_SAMPLE_BROKEN_UNTERMINATED_ARRAY); } void JsonEndToEndTest::TestObjectUnterminated() { TestUnterminated(JSON_SAMPLE_BROKEN_UNTERMINATED_OBJECT); } /*static*/ void JsonEndToEndTest::AddTests(BTestSuite& parent) { CppUnit::TestSuite& suite = *new CppUnit::TestSuite("JsonEndToEndTest"); suite.addTest(new CppUnit::TestCaller( "JsonEndToEndTest::TestNullA", &JsonEndToEndTest::TestNullA)); suite.addTest(new CppUnit::TestCaller( "JsonEndToEndTest::TestTrueA", &JsonEndToEndTest::TestTrueA)); suite.addTest(new CppUnit::TestCaller( "JsonEndToEndTest::TestFalseA", &JsonEndToEndTest::TestFalseA)); suite.addTest(new CppUnit::TestCaller( "JsonEndToEndTest::TestNumberA", &JsonEndToEndTest::TestNumberA)); suite.addTest(new CppUnit::TestCaller( "JsonEndToEndTest::TestStringA", &JsonEndToEndTest::TestStringA)); suite.addTest(new CppUnit::TestCaller( "JsonEndToEndTest::TestStringA2", &JsonEndToEndTest::TestStringA2)); suite.addTest(new CppUnit::TestCaller( "JsonEndToEndTest::TestStringB", &JsonEndToEndTest::TestStringB)); suite.addTest(new CppUnit::TestCaller( "JsonEndToEndTest::TestArrayA", &JsonEndToEndTest::TestArrayA)); suite.addTest(new CppUnit::TestCaller( "JsonEndToEndTest::TestArrayB", &JsonEndToEndTest::TestArrayB)); suite.addTest(new CppUnit::TestCaller( "JsonEndToEndTest::TestObjectA", &JsonEndToEndTest::TestObjectA)); suite.addTest(new CppUnit::TestCaller( "JsonEndToEndTest::TestStringUnterminated", &JsonEndToEndTest::TestStringUnterminated)); suite.addTest(new CppUnit::TestCaller( "JsonEndToEndTest::TestArrayUnterminated", &JsonEndToEndTest::TestArrayUnterminated)); suite.addTest(new CppUnit::TestCaller( "JsonEndToEndTest::TestHighVolumeStringParsing", &JsonEndToEndTest::TestHighVolumeStringParsing)); suite.addTest(new CppUnit::TestCaller( "JsonEndToEndTest::TestHighVolumeNumberParsing", &JsonEndToEndTest::TestHighVolumeNumberParsing)); suite.addTest(new CppUnit::TestCaller( "JsonEndToEndTest::TestHighVolumeStringSampleGenerationOnly", &JsonEndToEndTest::TestHighVolumeStringSampleGenerationOnly)); suite.addTest(new CppUnit::TestCaller( "JsonEndToEndTest::TestHighVolumeNumberSampleGenerationOnly", &JsonEndToEndTest::TestHighVolumeNumberSampleGenerationOnly)); parent.addTest("JsonEndToEndTest", &suite); }