123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- #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
|