/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include "testgen.hh" // < generated header #include "testgen2.hh" // < generated header #include "Serializer.hh" #include "Writer.hh" #include "Reader.hh" #include "Node.hh" #include "ValidSchema.hh" #include "Compiler.hh" #include "ResolvingReader.hh" #include "ResolverSchema.hh" #include "buffer/BufferPrint.hh" std::string gWriter ("jsonschemas/bigrecord"); std::string gReader ("jsonschemas/bigrecord2"); void printRecord(testgen::RootRecord &record) { using namespace testgen; std::cout << "mylong " << record.mylong << '\n'; std::cout << "inval1 " << record.nestedrecord.inval1 << '\n'; std::cout << "inval2 " << record.nestedrecord.inval2 << '\n'; std::cout << "inval3 " << record.nestedrecord.inval3 << '\n'; Map_of_int::MapType::const_iterator mapiter = record.mymap.value.begin(); while(mapiter != record.mymap.value.end()){ std::cout << "mymap " << mapiter->first << " " << mapiter->second << '\n'; ++mapiter; } Array_of_double::ArrayType::iterator arrayiter = record.myarray.value.begin(); while(arrayiter != record.myarray.value.end()) { std::cout << "myarray " << *arrayiter << '\n'; ++arrayiter; } std::cout << "myeum = " << record.myenum.value << '\n'; if(record.myunion.choice == 1) { const Map_of_int &theMap = record.myunion.getValue(); mapiter = theMap.value.begin(); while(mapiter != theMap.value.end()){ std::cout << "unionmap " << mapiter->first << " " << mapiter->second << '\n'; ++mapiter; } } if(record.anotherunion.choice == 0) { std::cout << "unionbytes "; const std::vector &val = record.anotherunion.getValue< std::vector >(); for(size_t i = 0; i < val.size(); ++i) { std::cout << i << ":" << static_cast(val[i]) << " "; } std::cout << '\n'; } std::cout << "mybool " << record.mybool << '\n'; std::cout << "inval1 " << record.anothernested.inval1 << '\n'; std::cout << "inval2 " << record.anothernested.inval2 << '\n'; std::cout << "inval3 " << record.anothernested.inval3 << '\n'; std::cout << "fixed "; for(size_t i = 0; i < record.myfixed.fixedSize; ++i) { std::cout << i << ":" << static_cast(record.myfixed.value[i]) << " "; } std::cout << '\n'; std::cout << "anotherint " << record.anotherint << '\n'; std::cout << "bytes "; for(size_t i = 0; i < record.bytes.size(); ++i) { std::cout << i << ":" << static_cast(record.bytes[i]) << " "; } std::cout << '\n'; } void printRecord(testgen2::RootRecord &record) { using namespace testgen2; std::cout << "mylong " << record.mylong << '\n'; std::cout << "inval1 " << record.nestedrecord.inval1 << '\n'; std::cout << "inval2 " << record.nestedrecord.inval2 << '\n'; std::cout << "inval3 " << record.nestedrecord.inval3 << '\n'; Map_of_long::MapType::const_iterator mapiter = record.mymap.value.begin(); while(mapiter != record.mymap.value.end()){ std::cout << "mymap " << mapiter->first << " " << mapiter->second << '\n'; ++mapiter; } Array_of_double::ArrayType::iterator arrayiter = record.myarray.value.begin(); while(arrayiter != record.myarray.value.end()) { std::cout << "myarray " << *arrayiter << '\n'; ++arrayiter; } std::cout << "myeum = " << record.myenum.value << '\n'; if(record.myunion.choice == 1) { const Map_of_float &theMap = record.myunion.getValue(); Map_of_float::MapType::const_iterator mapiter = theMap.value.begin(); while(mapiter != theMap.value.end()){ std::cout << "unionmap " << mapiter->first << " " << mapiter->second << '\n'; ++mapiter; } } std::cout << "unionbytes "; const std::vector &val = record.anotherunion; for(size_t i = 0; i < val.size(); ++i) { std::cout << i << ":" << static_cast(val[i]) << " "; } std::cout << '\n'; std::cout << "inval1 " << record.anothernested.inval1 << '\n'; std::cout << "inval2 " << record.anothernested.inval2 << '\n'; std::cout << "inval3 " << record.anothernested.inval3 << '\n'; if(record.myfixed.choice == 1) { const md5 &myfixed = record.myfixed.getValue(); std::cout << "fixed "; for(size_t i = 0; i < myfixed.fixedSize; ++i) { std::cout << i << ":" << static_cast(myfixed.value[i]) << " "; } std::cout << '\n'; } std::cout << "anotherint " << record.anotherint << '\n'; std::cout << "bytes "; for(size_t i = 0; i < record.bytes.size(); ++i) { std::cout << i << ":" << static_cast(record.bytes[i]) << " "; } std::cout << '\n'; std::cout << "newbool " << record.newbool << '\n'; } void setRecord(testgen::RootRecord &myRecord) { using namespace testgen; uint8_t fixed[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; myRecord.mylong = 212; myRecord.nestedrecord.inval1 = std::numeric_limits::min(); myRecord.nestedrecord.inval2 = "hello world"; myRecord.nestedrecord.inval3 = std::numeric_limits::max(); Map_of_int::GenericSetter setter = myRecord.mymap.genericSetter; Map_of_int::ValueType *val = setter(&myRecord.mymap, "one"); *val = 100; val = setter(&myRecord.mymap, "two"); *val = 200; myRecord.myarray.addValue(3434.9); myRecord.myarray.addValue(7343.9); myRecord.myarray.addValue(-63445.9); myRecord.myenum.value = testgen::ExampleEnum::one; testgen::Map_of_int map; map.addValue("one", 1); map.addValue("two", 2); myRecord.myunion.set_Map_of_int(map); std::vector vec; vec.push_back(1); vec.push_back(2); myRecord.anotherunion.set_bytes(vec); myRecord.mybool = true; myRecord.anothernested.inval1 = std::numeric_limits::max(); myRecord.anothernested.inval2 = "goodbye world"; myRecord.anothernested.inval3 = std::numeric_limits::min(); memcpy(myRecord.myfixed.value, fixed, testgen::md5::fixedSize); myRecord.anotherint = 4534; myRecord.bytes.push_back(10); myRecord.bytes.push_back(20); } struct TestCodeGenerator { void serializeToScreen() { std::cout << "Serialize:\n"; rmf_avro::Writer writer; rmf_avro::serialize(writer, myRecord_); std::cout << writer.buffer(); std::cout << "end Serialize\n"; } void serializeToScreenValid() { std::cout << "Validated Serialize:\n"; rmf_avro::ValidatingWriter writer(schema_); rmf_avro::serialize(writer, myRecord_); std::cout << writer.buffer(); std::cout << "end Validated Serialize\n"; } void checkArray(const testgen::Array_of_double &a1, const testgen::Array_of_double &a2) { BOOST_CHECK_EQUAL(a1.value.size(), 3U); BOOST_CHECK_EQUAL(a1.value.size(), a2.value.size()); for(size_t i = 0; i < a1.value.size(); ++i) { BOOST_CHECK_EQUAL(a1.value[i], a2.value[i]); } } void checkMap(const testgen::Map_of_int &map1, const testgen::Map_of_int &map2) { BOOST_CHECK_EQUAL(map1.value.size(), map2.value.size()); testgen::Map_of_int::MapType::const_iterator iter1 = map1.value.begin(); testgen::Map_of_int::MapType::const_iterator end = map1.value.end(); testgen::Map_of_int::MapType::const_iterator iter2 = map2.value.begin(); while(iter1 != end) { BOOST_CHECK_EQUAL(iter1->first, iter2->first); BOOST_CHECK_EQUAL(iter1->second, iter2->second); ++iter1; ++iter2; } } void checkBytes(const std::vector &v1, const std::vector &v2) { BOOST_CHECK_EQUAL(v1.size(), 2U); BOOST_CHECK_EQUAL(v1.size(), v2.size()); for(size_t i = 0; i < v1.size(); ++i) { BOOST_CHECK_EQUAL(v1[i], v2[i]); } } void checkNested(const testgen::Nested &rec1, const testgen::Nested &rec2) { BOOST_CHECK_EQUAL(rec1.inval1, rec2.inval1); BOOST_CHECK_EQUAL(rec1.inval2, rec2.inval2); BOOST_CHECK_EQUAL(rec1.inval3, rec2.inval3); } void checkOk(const testgen::RootRecord &rec1, const testgen::RootRecord &rec2) { BOOST_CHECK_EQUAL(rec1.mylong, rec1.mylong); checkNested(rec1.nestedrecord, rec2.nestedrecord); checkMap(rec1.mymap, rec2.mymap); checkArray(rec1.myarray, rec2.myarray); BOOST_CHECK_EQUAL(rec1.myenum.value, rec2.myenum.value); BOOST_CHECK_EQUAL(rec1.myunion.choice, rec2.myunion.choice); // in this test I know choice was 1 { BOOST_CHECK_EQUAL(rec1.myunion.choice, 1); checkMap(rec1.myunion.getValue(), rec2.myunion.getValue()); } BOOST_CHECK_EQUAL(rec1.anotherunion.choice, rec2.anotherunion.choice); // in this test I know choice was 0 { BOOST_CHECK_EQUAL(rec1.anotherunion.choice, 0); typedef std::vector mytype; checkBytes(rec1.anotherunion.getValue(), rec2.anotherunion.getValue()); } checkNested(rec1.anothernested, rec2.anothernested); BOOST_CHECK_EQUAL(rec1.mybool, rec2.mybool); for(int i = 0; i < static_cast(testgen::md5::fixedSize); ++i) { BOOST_CHECK_EQUAL(rec1.myfixed.value[i], rec2.myfixed.value[i]); } BOOST_CHECK_EQUAL(rec1.anotherint, rec2.anotherint); checkBytes(rec1.bytes, rec2.bytes); } void testParser() { rmf_avro::Writer s; rmf_avro::serialize(s, myRecord_); testgen::RootRecord inRecord; rmf_avro::Reader p(s.buffer()); rmf_avro::parse(p, inRecord); checkOk(myRecord_, inRecord); } void testParserValid() { rmf_avro::ValidatingWriter s (schema_); rmf_avro::serialize(s, myRecord_); testgen::RootRecord inRecord; rmf_avro::ValidatingReader p(schema_, s.buffer()); rmf_avro::parse(p, inRecord); checkOk(myRecord_, inRecord); } void testNameIndex() { const rmf_avro::NodePtr &node = schema_.root(); size_t index = 0; bool found = node->nameIndex("anothernested", index); BOOST_CHECK_EQUAL(found, true); BOOST_CHECK_EQUAL(index, 8U); found = node->nameIndex("myenum", index); BOOST_CHECK_EQUAL(found, true); BOOST_CHECK_EQUAL(index, 4U); const rmf_avro::NodePtr &enumNode = node->leafAt(index); found = enumNode->nameIndex("one", index); BOOST_CHECK_EQUAL(found, true); BOOST_CHECK_EQUAL(index, 1U); } void test() { std::cout << "Running code generation tests\n"; testNameIndex(); serializeToScreen(); serializeToScreenValid(); testParser(); testParserValid(); std::cout << "Finished code generation tests\n"; } TestCodeGenerator() { setRecord(myRecord_); std::ifstream in(gWriter.c_str()); rmf_avro::compileJsonSchema(in, schema_); } testgen::RootRecord myRecord_; rmf_avro::ValidSchema schema_; }; struct TestSchemaResolving { void checkArray(const testgen::Array_of_double &a1, const testgen2::Array_of_double &a2) { BOOST_CHECK_EQUAL(a1.value.size(), 3U); BOOST_CHECK_EQUAL(a1.value.size(), a2.value.size()); for(size_t i = 0; i < a1.value.size(); ++i) { BOOST_CHECK_EQUAL(a1.value[i], a2.value[i]); } } void checkMap(const testgen::Map_of_int &map1, const testgen2::Map_of_long &map2) { BOOST_CHECK_EQUAL(map1.value.size(), map2.value.size()); testgen::Map_of_int::MapType::const_iterator iter1 = map1.value.begin(); testgen::Map_of_int::MapType::const_iterator end = map1.value.end(); testgen2::Map_of_long::MapType::const_iterator iter2 = map2.value.begin(); while(iter1 != end) { BOOST_CHECK_EQUAL(iter1->first, iter2->first); BOOST_CHECK_EQUAL(static_cast(iter1->second), iter2->second); ++iter1; ++iter2; } } void checkMap(const testgen::Map_of_int &map1, const testgen2::Map_of_float &map2) { BOOST_CHECK_EQUAL(map1.value.size(), map2.value.size()); testgen::Map_of_int::MapType::const_iterator iter1 = map1.value.begin(); testgen::Map_of_int::MapType::const_iterator end = map1.value.end(); testgen2::Map_of_float::MapType::const_iterator iter2 = map2.value.begin(); while(iter1 != end) { BOOST_CHECK_EQUAL(iter1->first, iter2->first); BOOST_CHECK_EQUAL(static_cast(iter1->second), iter2->second); ++iter1; ++iter2; } } void checkBytes(const std::vector &v1, const std::vector &v2) { BOOST_CHECK_EQUAL(v1.size(), 2U); BOOST_CHECK_EQUAL(v1.size(), v2.size()); for(size_t i = 0; i < v1.size(); ++i) { BOOST_CHECK_EQUAL(v1[i], v2[i]); } } void checkNested(const testgen::Nested &rec1, const testgen2::Nested &rec2) { BOOST_CHECK_EQUAL(rec1.inval1, rec2.inval1); BOOST_CHECK_EQUAL(rec1.inval2, rec2.inval2); BOOST_CHECK_EQUAL(rec1.inval3, rec2.inval3); } void checkOk(const testgen::RootRecord &rec1, const testgen2::RootRecord &rec2) { BOOST_CHECK_EQUAL(rec1.mylong, rec1.mylong); checkNested(rec1.nestedrecord, rec2.nestedrecord); checkMap(rec1.mymap, rec2.mymap); checkArray(rec1.myarray, rec2.myarray); // enum was remapped from 1 to 2 BOOST_CHECK_EQUAL(rec1.myenum.value, 1); BOOST_CHECK_EQUAL(rec2.myenum.value, 2); // in this test I know choice was 1 { BOOST_CHECK_EQUAL(rec1.myunion.choice, 1); BOOST_CHECK_EQUAL(rec2.myunion.choice, 2); checkMap(rec1.myunion.getValue(), rec2.myunion.getValue()); } { BOOST_CHECK_EQUAL(rec1.anotherunion.choice, 0); typedef std::vector mytype; checkBytes(rec1.anotherunion.getValue(), rec2.anotherunion); } checkNested(rec1.anothernested, rec2.anothernested); BOOST_CHECK_EQUAL(rec2.newbool, false); BOOST_CHECK_EQUAL(rec2.myfixed.choice, 1); { const testgen2::md5 &myfixed2 = rec2.myfixed.getValue(); for(int i = 0; i < static_cast(testgen::md5::fixedSize); ++i) { BOOST_CHECK_EQUAL(rec1.myfixed.value[i], myfixed2.value[i]); } } } rmf_avro::InputBuffer serializeWriteRecordToBuffer() { std::ostringstream ostring; rmf_avro::Writer s; rmf_avro::serialize(s, writeRecord_); return s.buffer(); } void parseData(const rmf_avro::InputBuffer &buf, rmf_avro::ResolverSchema &xSchema) { rmf_avro::ResolvingReader r(xSchema, buf); rmf_avro::parse(r, readRecord_); } void test() { std::cout << "Running schema resolution tests\n"; testgen2::RootRecord_Layout layout; rmf_avro::ResolverSchema xSchema(writerSchema_, readerSchema_, layout); printRecord(writeRecord_); rmf_avro::InputBuffer buffer = serializeWriteRecordToBuffer(); parseData(buffer, xSchema); printRecord(readRecord_); checkOk(writeRecord_, readRecord_); std::cout << "Finished schema resolution tests\n"; } TestSchemaResolving() { setRecord(writeRecord_); std::ifstream win(gWriter.c_str()); rmf_avro::compileJsonSchema(win, writerSchema_); std::ifstream rin(gReader.c_str()); rmf_avro::compileJsonSchema(rin, readerSchema_); } testgen::RootRecord writeRecord_; rmf_avro::ValidSchema writerSchema_; testgen2::RootRecord readRecord_; rmf_avro::ValidSchema readerSchema_; }; template void addTestCase(boost::unit_test::test_suite &test) { boost::shared_ptr newtest( new T ); test.add( BOOST_CLASS_TEST_CASE( &T::test, newtest )); } boost::unit_test::test_suite* init_unit_test_suite( int argc, char* argv[] ) { using namespace boost::unit_test; const char *srcPath = getenv("top_srcdir"); if(srcPath) { std::string srcPathStr(srcPath); gWriter = srcPathStr + '/' + gWriter; gReader = srcPathStr + '/' + gReader; } else { if(argc > 1) { gWriter = argv[1]; } if(argc > 2) { gReader = argv[2]; } } std::cout << "Using writer schema " << gWriter << std::endl; std::cout << "Using reader schema " << gReader << std::endl; test_suite* test= BOOST_TEST_SUITE( "Avro C++ unit test suite" ); addTestCase(*test); addTestCase(*test); return test; }