summaryrefslogtreecommitdiffstats
path: root/src/rapidjson/test/perftest/schematest.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/rapidjson/test/perftest/schematest.cpp216
1 files changed, 216 insertions, 0 deletions
diff --git a/src/rapidjson/test/perftest/schematest.cpp b/src/rapidjson/test/perftest/schematest.cpp
new file mode 100644
index 000000000..468f5fe6f
--- /dev/null
+++ b/src/rapidjson/test/perftest/schematest.cpp
@@ -0,0 +1,216 @@
+#include "perftest.h"
+
+#if TEST_RAPIDJSON
+
+#include "rapidjson/schema.h"
+#include <ctime>
+#include <string>
+#include <vector>
+
+#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])
+
+using namespace rapidjson;
+
+template <typename Allocator>
+static char* ReadFile(const char* filename, Allocator& allocator) {
+ const char *paths[] = {
+ "",
+ "bin/",
+ "../bin/",
+ "../../bin/",
+ "../../../bin/"
+ };
+ char buffer[1024];
+ FILE *fp = 0;
+ for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
+ sprintf(buffer, "%s%s", paths[i], filename);
+ fp = fopen(buffer, "rb");
+ if (fp)
+ break;
+ }
+
+ if (!fp)
+ return 0;
+
+ fseek(fp, 0, SEEK_END);
+ size_t length = static_cast<size_t>(ftell(fp));
+ fseek(fp, 0, SEEK_SET);
+ char* json = reinterpret_cast<char*>(allocator.Malloc(length + 1));
+ size_t readLength = fread(json, 1, length, fp);
+ json[readLength] = '\0';
+ fclose(fp);
+ return json;
+}
+
+class Schema : public PerfTest {
+public:
+ Schema() {}
+
+ virtual void SetUp() {
+ PerfTest::SetUp();
+
+ const char* filenames[] = {
+ "additionalItems.json",
+ "additionalProperties.json",
+ "allOf.json",
+ "anyOf.json",
+ "default.json",
+ "definitions.json",
+ "dependencies.json",
+ "enum.json",
+ "items.json",
+ "maximum.json",
+ "maxItems.json",
+ "maxLength.json",
+ "maxProperties.json",
+ "minimum.json",
+ "minItems.json",
+ "minLength.json",
+ "minProperties.json",
+ "multipleOf.json",
+ "not.json",
+ "oneOf.json",
+ "pattern.json",
+ "patternProperties.json",
+ "properties.json",
+ "ref.json",
+ "refRemote.json",
+ "required.json",
+ "type.json",
+ "uniqueItems.json"
+ };
+
+ char jsonBuffer[65536];
+ MemoryPoolAllocator<> jsonAllocator(jsonBuffer, sizeof(jsonBuffer));
+
+ for (size_t i = 0; i < ARRAY_SIZE(filenames); i++) {
+ char filename[FILENAME_MAX];
+ sprintf(filename, "jsonschema/tests/draft4/%s", filenames[i]);
+ char* json = ReadFile(filename, jsonAllocator);
+ if (!json) {
+ printf("json test suite file %s not found", filename);
+ return;
+ }
+
+ Document d;
+ d.Parse(json);
+ if (d.HasParseError()) {
+ printf("json test suite file %s has parse error", filename);
+ return;
+ }
+
+ for (Value::ConstValueIterator schemaItr = d.Begin(); schemaItr != d.End(); ++schemaItr) {
+ std::string schemaDescription = (*schemaItr)["description"].GetString();
+ if (IsExcludeTestSuite(schemaDescription))
+ continue;
+
+ TestSuite* ts = new TestSuite;
+ ts->schema = new SchemaDocument((*schemaItr)["schema"]);
+
+ const Value& tests = (*schemaItr)["tests"];
+ for (Value::ConstValueIterator testItr = tests.Begin(); testItr != tests.End(); ++testItr) {
+ if (IsExcludeTest(schemaDescription + ", " + (*testItr)["description"].GetString()))
+ continue;
+
+ Document* d2 = new Document;
+ d2->CopyFrom((*testItr)["data"], d2->GetAllocator());
+ ts->tests.push_back(d2);
+ }
+ testSuites.push_back(ts);
+ }
+ }
+ }
+
+ virtual void TearDown() {
+ PerfTest::TearDown();
+ for (TestSuiteList::const_iterator itr = testSuites.begin(); itr != testSuites.end(); ++itr)
+ delete *itr;
+ testSuites.clear();
+ }
+
+private:
+ // Using the same exclusion in https://github.com/json-schema/JSON-Schema-Test-Suite
+ static bool IsExcludeTestSuite(const std::string& description) {
+ const char* excludeTestSuites[] = {
+ //lost failing these tests
+ "remote ref",
+ "remote ref, containing refs itself",
+ "fragment within remote ref",
+ "ref within remote ref",
+ "change resolution scope",
+ // these below were added to get jsck in the benchmarks)
+ "uniqueItems validation",
+ "valid definition",
+ "invalid definition"
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(excludeTestSuites); i++)
+ if (excludeTestSuites[i] == description)
+ return true;
+ return false;
+ }
+
+ // Using the same exclusion in https://github.com/json-schema/JSON-Schema-Test-Suite
+ static bool IsExcludeTest(const std::string& description) {
+ const char* excludeTests[] = {
+ //lots of validators fail these
+ "invalid definition, invalid definition schema",
+ "maxLength validation, two supplementary Unicode code points is long enough",
+ "minLength validation, one supplementary Unicode code point is not long enough",
+ //this is to get tv4 in the benchmarks
+ "heterogeneous enum validation, something else is invalid"
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(excludeTests); i++)
+ if (excludeTests[i] == description)
+ return true;
+ return false;
+ }
+
+ Schema(const Schema&);
+ Schema& operator=(const Schema&);
+
+protected:
+ typedef std::vector<Document*> DocumentList;
+
+ struct TestSuite {
+ TestSuite() : schema() {}
+ ~TestSuite() {
+ delete schema;
+ for (DocumentList::iterator itr = tests.begin(); itr != tests.end(); ++itr)
+ delete *itr;
+ }
+ SchemaDocument* schema;
+ DocumentList tests;
+ };
+
+ typedef std::vector<TestSuite* > TestSuiteList;
+ TestSuiteList testSuites;
+};
+
+TEST_F(Schema, TestSuite) {
+ char validatorBuffer[65536];
+ MemoryPoolAllocator<> validatorAllocator(validatorBuffer, sizeof(validatorBuffer));
+
+ const int trialCount = 100000;
+ int testCount = 0;
+ clock_t start = clock();
+ for (int i = 0; i < trialCount; i++) {
+ for (TestSuiteList::const_iterator itr = testSuites.begin(); itr != testSuites.end(); ++itr) {
+ const TestSuite& ts = **itr;
+ GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<> >, MemoryPoolAllocator<> > validator(*ts.schema, &validatorAllocator);
+ for (DocumentList::const_iterator testItr = ts.tests.begin(); testItr != ts.tests.end(); ++testItr) {
+ validator.Reset();
+ (*testItr)->Accept(validator);
+ testCount++;
+ }
+ validatorAllocator.Clear();
+ }
+ }
+ clock_t end = clock();
+ double duration = double(end - start) / CLOCKS_PER_SEC;
+ printf("%d trials in %f s -> %f trials per sec\n", trialCount, duration, trialCount / duration);
+ printf("%d tests per trial\n", testCount / trialCount);
+}
+
+#endif