createString("MyMonster"); $name = $fbb->createString('Fred'); \MyGame\Example\Monster::startMonster($fbb); \MyGame\Example\Monster::addName($fbb, $name); $enemy = \MyGame\Example\Monster::endMonster($fbb); $inv = \MyGame\Example\Monster::CreateInventoryVector($fbb, array(0, 1, 2, 3, 4)); $fred = $fbb->createString('Fred'); \MyGame\Example\Monster::StartMonster($fbb); \MyGame\Example\Monster::AddName($fbb, $fred); $mon2 = \MyGame\Example\Monster::EndMonster($fbb); \MyGame\Example\Monster::StartTest4Vector($fbb, 2); \MyGame\Example\Test::CreateTest($fbb, 10, 20); \MyGame\Example\Test::CreateTest($fbb, 30, 40); $test4 = $fbb->endVector(); $testArrayOfString = \MyGame\Example\Monster::CreateTestarrayofstringVector($fbb, array( $fbb->createString('test1'), $fbb->createString('test2') )); \MyGame\Example\Monster::StartMonster($fbb); \MyGame\Example\Monster::AddPos($fbb, \MyGame\Example\Vec3::CreateVec3($fbb, 1.0, 2.0, 3.0, //float 3.0, // double \MyGame\Example\Color::Green, 5, //short 6)); \MyGame\Example\Monster::AddHp($fbb, 80); \MyGame\Example\Monster::AddName($fbb, $str); \MyGame\Example\Monster::AddInventory($fbb, $inv); \MyGame\Example\Monster::AddTestType($fbb, \MyGame\Example\Any::Monster); \MyGame\Example\Monster::AddTest($fbb, $mon2); \MyGame\Example\Monster::AddTest4($fbb, $test4); \MyGame\Example\Monster::AddTestarrayofstring($fbb, $testArrayOfString); \MyGame\Example\Monster::AddEnemy($fbb, $enemy); \MyGame\Example\Monster::AddTestbool($fbb, true); $mon = \MyGame\Example\Monster::EndMonster($fbb); \MyGame\Example\Monster::FinishMonsterBuffer($fbb, $mon); // Test it: test_buffer($assert, $fbb->dataBuffer()); testByteBuffer($assert); fuzzTest1($assert); // testUnicode($assert); echo 'FlatBuffers php test: completed successfully' . PHP_EOL; } try { main(); exit(0); } catch(Exception $e) { printf("Fatal error: Uncaught exception '%s' with message '%s. in %s:%d\n", get_class($e), $e->getMessage(), $e->getFile(), $e->getLine()); printf("Stack trace:\n"); echo $e->getTraceAsString() . PHP_EOL; printf(" thrown in in %s:%d\n", $e->getFile(), $e->getLine()); die(-1); } function test_buffer(Assert $assert, Google\FlatBuffers\ByteBuffer $bb) { $assert->ok(MyGame\Example\Monster::MonsterBufferHasIdentifier($bb)); $monster = \MyGame\Example\Monster::GetRootAsMonster($bb); $assert->strictEqual($monster->GetHp(), 80); $assert->strictEqual($monster->GetMana(), 150); // default $assert->strictEqual($monster->GetName(), 'MyMonster'); $pos = $monster->GetPos(); $assert->strictEqual($pos->GetX(), 1.0); $assert->strictEqual($pos->GetY(), 2.0); $assert->strictEqual($pos->GetZ(), 3.0); $assert->Equal($pos->GetTest1(), 3.0); $assert->strictEqual($pos->GetTest2(), \MyGame\Example\Color::Green); $t = $pos->GetTest3(); $assert->strictEqual($t->GetA(), 5); $assert->strictEqual($t->GetB(), 6); $assert->strictEqual($monster->GetTestType(), \MyGame\Example\Any::Monster); $monster2 = new \MyGame\Example\Monster(); $assert->strictEqual($monster->GetTest($monster2) != null, true); $assert->strictEqual($monster2->GetName(), 'Fred'); $assert->strictEqual($monster->GetInventoryLength(), 5); $invsum = 0; for ($i = 0; $i < $monster->GetInventoryLength(); $i++) { $invsum += $monster->GetInventory($i); } $assert->strictEqual($invsum, 10); $assert->strictEqual(bin2hex($monster->GetInventoryBytes()), "0001020304"); $test_0 = $monster->GetTest4(0); $test_1 = $monster->GetTest4(1); $assert->strictEqual($monster->GetTest4Length(), 2); $assert->strictEqual($test_0->GetA() + $test_0->GetB() + $test_1->GetA() + $test_1->GetB(), 100); $assert->strictEqual($monster->GetTestarrayofstringLength(), 2); $assert->strictEqual($monster->GetTestarrayofstring(0), 'test1'); $assert->strictEqual($monster->GetTestarrayofstring(1), 'test2'); $fred = $monster->getEnemy(); $assert->Equal('Fred', $fred->getName()); $assert->strictEqual($monster->GetTestbool(), true); } //function testUnicode(Assert $assert) { // // missing unicode_test.mon, implemented later // $correct = file_get_contents('unicode_test.mon'); // $json = json_decode(file_get_contents('unicode_test.json')); // // // Test reading // $bb = flatbuffers\ByteBuffer::Wrap($correct); // $monster = \MyGame\Example\Monster::GetRootAsMonster($bb); // $assert->strictEqual($monster->GetName(), $json["name"]); // // //$assert->deepEqual(new Buffer(monster.name(flatbuffers.Encoding.UTF8_BYTES)), new Buffer(json.name)); // //assert.strictEqual(monster.testarrayoftablesLength(), json.testarrayoftables.length); // foreach ($json["testarrayoftables"]as $i => $table) { // $value = $monster->GetTestArrayOfTables($i); // $assert->strictEqual($value->GetName(), $table["name"]); // //assert.deepEqual(new Buffer(value.name(flatbuffers.Encoding.UTF8_BYTES)), new Buffer(table.name)); // } // $assert->strictEqual($monster->GetTestarrayofstringLength(), $json["testarrayofstring"]["length"]); // foreach ($json["testarrayofstring"] as $i => $string) { // $assert->strictEqual($monster->GetTestarrayofstring($i), $string); // //assert.deepEqual(new Buffer(monster.testarrayofstring(i, flatbuffers.Encoding.UTF8_BYTES)), new Buffer(string)); // } // // // Test writing // $fbb = new FlatBuffers\FlatBufferBuilder(1); // $name = $fbb->CreateString($json["name"]); // $testarrayoftablesOffsets = array_map(function($table) use($fbb) { // $name = $fbb->CreateString($table["name"]); // \MyGame\Example\Monster::StartMonster($fbb); // \MyGame\Example\Monster::AddName($fbb, $name); // return \MyGame\Example\Monster::EndMonster($fbb); // }, $json["testarrayoftables"]); // $testarrayoftablesOffset = \MyGame\Example\Monster::CreateTestarrayoftablesVector($fbb, // $testarrayoftablesOffsets); //// $testarrayofstringOffset = \MyGame\Example\Monster::CreateTestarrayofstringVector($fbb, //// $json["testarrayofstring"].map(function(string) { return fbb.createString(string); })); // // \MyGame\Example\Monster::startMonster($fbb); // \MyGame\Example\Monster::addTestarrayofstring($fbb, $testarrayoftablesOffset); // \MyGame\Example\Monster::addTestarrayoftables($fbb, $testarrayoftablesOffset); // \MyGame\Example\Monster::addName($fbb, $name); // \MyGame\Example\Monster::finishMonsterBuffer($fbb, \MyGame\Example\Monster::endMonster($fbb)); // //;assert.deepEqual(new Buffer(fbb.asUint8Array()), correct); //} // Low level stress/fuzz test: serialize/deserialize a variety of // different kinds of data in different combinations function fuzzTest1(Assert $assert) { // Values we're testing against: chosen to ensure no bits get chopped // off anywhere, and also be different from eachother. $bool_val = true; $char_val = -127; // 0x81 $uchar_val = 0xFF; $short_val = -32222; // 0x8222; $ushort_val = 0xFEEE; $int_val = 0x7fffffff | 0; // for now $uint_val = 1; $long_val = 2; $ulong_val = 3; // var uint_val = 0xFDDDDDDD; // var long_val = new flatbuffers.Long(0x44444444, 0x84444444); // var ulong_val = new flatbuffers.Long(0xCCCCCCCC, 0xFCCCCCCC); $float_val = 3.14159; $double_val = 3.14159265359; $test_values_max = 11; $fields_per_object = 4; // current implementation is not good at encoding. $num_fuzz_objects = 1000; $builder = new Google\FlatBuffers\FlatBufferBuilder(1); // can't use same implementation due to PHP_INTMAX overflow issue. // we use mt_rand function to reproduce fuzzy test. mt_srand(48271); $objects = array(); // Generate num_fuzz_objects random objects each consisting of // fields_per_object fields, each of a random type. for ($i = 0; $i < $num_fuzz_objects; $i++) { $builder->startObject($fields_per_object); for ($f = 0; $f < $fields_per_object; $f++) { $choice = mt_rand() % $test_values_max; switch ($choice) { case 0: $builder->addBoolX($f, $bool_val, 0); break; case 1: $builder->addByteX($f, $char_val, 0); break; case 2: $builder->addSbyteX($f, $uchar_val, 0); break; case 3: $builder->addShortX($f, $short_val, 0); break; case 4: $builder->addUshortX($f, $ushort_val, 0); break; case 5: $builder->addIntX($f, $int_val, 0); break; case 6: $builder->addUintX($f, $uint_val, 0); break; case 7: $builder->addLongX($f, $long_val, 0); break; case 8: $builder->addUlongX($f, $ulong_val, 0); break; case 9: $builder->addFloatX($f, $float_val, 0); break; case 10: $builder->addDoubleX($f, $double_val, 0); break; } } $objects[] = $builder->endObject(); } $builder->prep(8, 0); // Align whole buffer. mt_srand(48271); // Reset $builder->finish($objects[count($objects) - 1]); $view = Google\FlatBuffers\ByteBuffer::wrap($builder->sizedByteArray()); for ($i = 0; $i < $num_fuzz_objects; $i++) { $offset = $view->capacity() - $objects[$i]; for ($f = 0; $f < $fields_per_object; $f++) { $choice = mt_rand() % $test_values_max; $vtable_offset = fieldIndexToOffset($f); $vtable = $offset - $view->getInt($offset); $assert->ok($vtable_offset < $view->getShort($vtable)); $field_offset = $offset + $view->getShort($vtable + $vtable_offset); switch ($choice) { case 0: $assert->strictEqual(!!$view->getBool($field_offset), $bool_val); break; case 1: $assert->strictEqual($view->getSbyte($field_offset), $char_val); break; case 2: $assert->strictEqual($view->getByte($field_offset), $uchar_val); break; case 3: $assert->strictEqual($view->getShort($field_offset), $short_val); break; case 4: $assert->strictEqual($view->getUShort($field_offset), $ushort_val); break; case 5: $assert->strictEqual($view->getInt($field_offset), $int_val); break; case 6: $assert->strictEqual($view->getUint($field_offset), $uint_val); break; case 7: if (PHP_INT_SIZE <= 4) break; $assert->strictEqual($view->getLong($field_offset), $long_val); break; case 8: if (PHP_INT_SIZE <= 4) break; $assert->strictEqual($view->getUlong($field_offset), $ulong_val); break; case 9: $assert->strictEqual(floor($view->getFloat($field_offset)), floor($float_val)); break; case 10: $assert->strictEqual($view->getDouble($field_offset), $double_val); break; } } } } function fieldIndexToOffset($field_id) { // Should correspond to what EndTable() below builds up. $fixed_fields = 2; // Vtable size and Object Size. return ($field_id + $fixed_fields) * 2; } function testByteBuffer(Assert $assert) { //Test: ByteBuffer_Length_MatchesBufferLength $buffer = str_repeat("\0", 100); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Equal($uut->capacity(), strlen($buffer)); //Test: ByteBuffer_PutBytePopulatesBufferAtZeroOffset $buffer = "\0"; $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $uut->putByte(0, "\x63"); // 99 $assert->Equal("\x63", $uut->_buffer[0]); // don't share buffer as php user might confuse reference. //Test: ByteBuffer_PutByteCannotPutAtOffsetPastLength $buffer = "\0"; $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Throws(new OutOfRangeException(), function() use ($uut) { $uut->putByte(1, "\x63"); // 99 }); //Test: ByteBuffer_PutShortPopulatesBufferCorrectly $buffer = str_repeat("\0", 2); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $uut->putShort(0, 1); // Ensure Endiannes was written correctly $assert->Equal(chr(0x01), $uut->_buffer[0]); $assert->Equal(chr(0x00), $uut->_buffer[1]); $buffer = str_repeat("\0", 2); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $uut->putShort(0, -32768); // Ensure Endiannes was written correctly $assert->Equal(chr(0x00), $uut->_buffer[0]); $assert->Equal(chr(0x80), $uut->_buffer[1]); //Test: ByteBuffer_PutShortCannotPutAtOffsetPastLength $buffer = "\0"; $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Throws(new OutOfRangeException(), function() use ($uut) { $uut->putShort(2, 2); // 99 }); //Test: ByteBuffer_PutShortChecksLength $buffer = "\0"; $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Throws(new OutOfRangeException(), function() use ($uut) { $uut->putShort(0, 2); // 99 }); //Test: ByteBuffer_PutShortChecksLengthAndOffset $buffer = str_repeat("\0", 2); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Throws(new OutOfRangeException(), function() use ($uut) { $uut->putShort(1, 2); // 99 }); //Test: ByteBuffer_PutIntPopulatesBufferCorrectly $buffer = str_repeat("\0", 4); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $uut->putInt(0, 0x0A0B0C0D); $assert->Equal(chr(0x0D), $uut->_buffer[0]); $assert->Equal(chr(0x0C), $uut->_buffer[1]); $assert->Equal(chr(0x0B), $uut->_buffer[2]); $assert->Equal(chr(0x0A), $uut->_buffer[3]); $buffer = str_repeat("\0", 4); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $uut->putInt(0, -2147483648); $assert->Equal(chr(0x00), $uut->_buffer[0]); $assert->Equal(chr(0x00), $uut->_buffer[1]); $assert->Equal(chr(0x00), $uut->_buffer[2]); $assert->Equal(chr(0x80), $uut->_buffer[3]); //Test: ByteBuffer_PutIntCannotPutAtOffsetPastLength $buffer = str_repeat("\0", 4); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Throws(new OutOfRangeException(), function() use ($uut) { $uut->putInt(2, 0x0A0B0C0D); }); //Test: ByteBuffer_PutIntChecksLength $buffer = str_repeat("\0", 1); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Throws(new OutOfRangeException(), function() use ($uut) { $uut->putInt(0, 0x0A0B0C0D); }); //Test: ByteBuffer_PutIntChecksLengthAndOffset $buffer = str_repeat("\0", 4); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Throws(new OutOfRangeException(), function() use ($uut) { $uut->putInt(2, 0x0A0B0C0D); }); if (PHP_INT_SIZE > 4) { //Test: ByteBuffer_PutLongPopulatesBufferCorrectly $buffer = str_repeat("\0", 8); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $uut->putLong(0, 0x010203040A0B0C0D); $assert->Equal(chr(0x0D), $uut->_buffer[0]); $assert->Equal(chr(0x0C), $uut->_buffer[1]); $assert->Equal(chr(0x0B), $uut->_buffer[2]); $assert->Equal(chr(0x0A), $uut->_buffer[3]); $assert->Equal(chr(0x04), $uut->_buffer[4]); $assert->Equal(chr(0x03), $uut->_buffer[5]); $assert->Equal(chr(0x02), $uut->_buffer[6]); $assert->Equal(chr(0x01), $uut->_buffer[7]); //Test: ByteBuffer_PutLongCannotPutAtOffsetPastLength $buffer = str_repeat("\0", 8); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Throws(new OutOfRangeException(), function() use ($uut) { $uut->putLong(2, 0x010203040A0B0C0D); }); //Test: ByteBuffer_PutLongCannotPutAtOffsetPastLength $buffer = str_repeat("\0", 1); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Throws(new OutOfRangeException(), function() use ($uut) { $uut->putLong(0, 0x010203040A0B0C0D); }); //Test: ByteBuffer_PutLongChecksLengthAndOffset $buffer = str_repeat("\0", 8); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Throws(new OutOfRangeException(), function() use ($uut) { $uut->putLong(2, 0x010203040A0B0C0D); }); } //Test: ByteBuffer_GetByteReturnsCorrectData $buffer = str_repeat("\0", 1); $buffer[0] = "\x63"; $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Equal("\x63", $uut->get(0)); //Test: ByteBuffer_GetByteChecksOffset $buffer = str_repeat("\0", 1); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Throws(new OutOfRangeException(), function() use ($uut) { $uut->get(1); }); //Test: ByteBuffer_GetShortReturnsCorrectData $buffer = str_repeat("\0", 2); $buffer[0] = chr(0x01); $buffer[1] = chr(0x00); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Equal(1, $uut->getShort(0)); //Test: ByteBuffer_GetShortReturnsCorrectData (signed value) $buffer = str_repeat("\0", 2); $buffer[0] = chr(0x00); $buffer[1] = chr(0x80); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Equal(-32768, $uut->getShort(0)); //Test: ByteBuffer_GetShortChecksOffset $buffer = str_repeat("\0", 2); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Throws(new OutOfRangeException(), function() use ($uut) { $uut->getShort(2); }); //Test: ByteBuffer_GetShortChecksLength $buffer = str_repeat("\0", 2); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Throws(new OutOfRangeException(), function() use ($uut) { $uut->getShort(1); }); //Test: ByteBuffer_GetIntReturnsCorrectData $buffer = str_repeat("\0", 4); $buffer[0] = chr(0x0D); $buffer[1] = chr(0x0C); $buffer[2] = chr(0x0B); $buffer[3] = chr(0x0A); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Equal(0x0A0B0C0D, $uut->getInt(0)); $buffer = str_repeat("\0", 4); $buffer[0] = chr(0x00); $buffer[1] = chr(0x00); $buffer[2] = chr(0x00); $buffer[3] = chr(0x80); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Equal(-2147483648, $uut->getInt(0)); //Test: ByteBuffer_GetIntChecksOffset $buffer = str_repeat("\0", 4); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Throws(new OutOfRangeException(), function() use ($uut) { $uut->getInt(4); }); //Test: ByteBuffer_GetIntChecksLength $buffer = str_repeat("\0", 2); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Throws(new OutOfRangeException(), function() use ($uut) { $uut->getInt(0); }); if (PHP_INT_SIZE > 4) { //Test: ByteBuffer_GetLongReturnsCorrectData $buffer = str_repeat("\0", 8); $buffer[0] = chr(0x0D); $buffer[1] = chr(0x0C); $buffer[2] = chr(0x0B); $buffer[3] = chr(0x0A); $buffer[4] = chr(0x04); $buffer[5] = chr(0x03); $buffer[6] = chr(0x02); $buffer[7] = chr(0x01); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Equal(0x010203040A0B0C0D, $uut->getLong(0)); //Test: Signed Long $buffer = str_repeat("\0", 8); $buffer[0] = chr(0x00); $buffer[1] = chr(0x00); $buffer[2] = chr(0x00); $buffer[3] = chr(0x00); $buffer[4] = chr(0x00); $buffer[5] = chr(0x00); $buffer[6] = chr(0x00); $buffer[7] = chr(0x80); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Equal(-1 << 63, $uut->getLong(0)); } //Test: ByteBuffer_GetLongChecksOffset $buffer = str_repeat("\0", 8); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Throws(new OutOfRangeException(), function() use ($uut) { $uut->getLong(8); }); //Test: ByteBuffer_GetLongChecksLength $buffer = str_repeat("\0", 7); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Throws(new OutOfRangeException(), function() use ($uut) { $uut->getLong(0); }); //Test: big endian $buffer = str_repeat("\0", 2); // 0xFF 0x00 // Little Endian: 255 // Big Endian: 65280 $buffer[0] = chr(0xff); $buffer[1] = chr(0x00); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Equal(65280, $uut->readLittleEndian(0, 2, true)); $buffer = str_repeat("\0", 4); $buffer[0] = chr(0x0D); $buffer[1] = chr(0x0C); $buffer[2] = chr(0x0B); $buffer[3] = chr(0x0A); $uut = Google\FlatBuffers\ByteBuffer::wrap($buffer); $assert->Equal(0x0D0C0B0A, $uut->readLittleEndian(0, 4, true)); } class Assert { public function ok($result, $message = "") { if (!$result){ throw new Exception(!empty($message) ? $message : "{$result} is not true."); } } public function Equal($result, $expected, $message = "") { if ($result != $expected) { throw new Exception(!empty($message) ? $message : "given the result {$result} is not equals as {$expected}"); } } public function strictEqual($result, $expected, $message = "") { if ($result !== $expected) { throw new Exception(!empty($message) ? $message : "given the result {$result} is not strict equals as {$expected}"); } } public function Throws($class, Callable $callback) { try { $callback(); throw new \Exception("passed statement don't throw an exception."); } catch (\Exception $e) { if (get_class($e) != get_class($class)) { throw new Exception("passed statement doesn't throw " . get_class($class) . ". throws " . get_class($e) . ": {$e->getMessage()}"); } } } }