TEST(SerializerTest, Clear) { Serializer s; s << AmfDouble(0.5); s.clear(); ASSERT_EQ(v8 { }, s.data()); s << AmfDouble(-1.2); v8 expected { 0x05, 0xBF, 0xF3, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33 }; ASSERT_EQ(expected, s.data()); }
TEST(ObjectSerializationTest, DynamicSealedNamedObject) { AmfObjectTraits traits("de.ventero.AmfTest", true, false); AmfObject obj(traits); obj.addSealedProperty("sealedProp", AmfDouble(3.14159)); obj.addDynamicProperty("dynamicProp", AmfInteger(17)); isEqual(v8 { 0x0a, // AMF_OBJECT 0x1b, // 0b11011, U29O-traits, dynamic, 1 sealed property // class-name UTF-8-vr "de.ventero.AmfTest" 0x25, 0x64, 0x65, 0x2e, 0x76, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x6f, 0x2e, 0x41, 0x6d, 0x66, 0x54, 0x65, 0x73, 0x74, // sealed property names // UTF-8-vr "sealedProp" 0x15, 0x73, 0x65, 0x61, 0x6c, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x70, // sealed property values // AmfDouble 3.14159 0x05, 0x40, 0x09, 0x21, 0xf9, 0xf0, 0x1b, 0x86, 0x6e, // dynamic members // UTF-8-vr dynamicProp 0x17, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x50, 0x72, 0x6f, 0x70, // AmfInteger 17 0x04, 0x11, // end of dynamic members 0x01 }, obj); }
TEST(SerializationContext, Clear) { SerializationContext ctx; // Verify the context is initially empty. ASSERT_THROW(ctx.getString(0), std::out_of_range); ASSERT_THROW(ctx.getTraits(0), std::out_of_range); ASSERT_THROW(ctx.getObject<AmfNull>(0), std::out_of_range); // Add a few objects. ctx.addString("foo"); ctx.addString("bar"); ctx.addTraits(AmfObjectTraits("asd", false, false)); ctx.addTraits(AmfObjectTraits("foobar", false, false)); ctx.addTraits(AmfObjectTraits("qux", true, false)); ctx.addObject(AmfInteger(17)); ctx.addObject(AmfDouble(1.0)); ASSERT_NO_THROW(ctx.getString(1)); ASSERT_NO_THROW(ctx.getTraits(2)); ASSERT_NO_THROW(ctx.getObject<AmfDouble>(1)); // Clear and check that it's empty again. ctx.clear(); ASSERT_THROW(ctx.getString(0), std::out_of_range); ASSERT_THROW(ctx.getTraits(0), std::out_of_range); ASSERT_THROW(ctx.getObject<AmfNull>(0), std::out_of_range); }
TEST(SerializerTest, MultipleDoubleValues) { Serializer s; s << AmfDouble(0.5) << AmfDouble(2.5e+51); v8 expected { 0x05, 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x4A, 0x9A, 0xBA, 0x47, 0x14, 0x95, 0x7D, 0x30 }; ASSERT_EQ(expected, s.data()); s << AmfDouble(-1.2); expected = { 0x05, 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x4A, 0x9A, 0xBA, 0x47, 0x14, 0x95, 0x7D, 0x30, 0x05, 0xBF, 0xF3, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33 }; ASSERT_EQ(expected, s.data()); }
std::vector<u8> serialize() const { // AmfDate is date-marker (U29O-ref | (U29D-value date-time)), // where U29D-value is 1 and date-time is a int64 encoded as double std::vector<u8> buf { AMF_DATE, 0x01 }; std::vector<u8> date(AmfDouble(value).serialize()); // skip the AMF_DOUBLE marker buf.insert(buf.end(), date.begin() + 1, date.end()); return buf; }
TEST(DictionarySerializationTest, NumberKeys) { AmfDictionary d(false, true); d.insert(AmfDouble(-0.5), AmfInteger(3)); isEqual(v8 { 0x11, 0x03, // 1 element 0x01, // weak keys 0x05, 0xBF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // AmfDouble -0.5 0x04, 0x03 // AmfInteger 3 }, d); d = AmfDictionary(false, false); d.insert(AmfDouble(1.2345678912345e+35), AmfArray()); isEqual(v8 { 0x11, 0x03, // 1 element 0x00, // no weak keys 0x05, 0x47, 0x37, 0xC6, 0xE3, 0xC0, 0x32, 0xF7, 0x20, // AmfDouble 1.2345678912345e+35 0x09, 0x01, 0x01 // empty AmfArray }, d); }
TEST(SerializerTest, MultipleMixedValues) { Serializer s; s << AmfDouble(0.5) << AmfInteger(0x3ff) << AmfString("bar") << AmfNull(); v8 expected { 0x05, 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x87, 0x7F, 0x06, 0x07, 0x62, 0x61, 0x72, 0x01 }; ASSERT_EQ(expected, s.data()); }
TEST(DictionarySerializationTest, NumberAsStringKeys) { AmfDictionary d(true, true); d.insert(AmfDouble(-0.5), AmfInteger(3)); isEqual(v8 { 0x11, 0x03, // 1 element 0x01, // weak keys 0x06, 0x09, 0x2D, 0x30, 0x2E, 0x35, // AmfString "-0.5" 0x04, 0x03 // AmfInteger 3 }, d); d = AmfDictionary(true, false); d.insert(AmfDouble(1.2345678912345e+35), AmfArray()); isEqual(v8 { 0x11, 0x03, // 1 element 0x00, // no weak keys // AmfString "1.2345678912345e+35" 0x06, 0x27, 0x31, 0x2e, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x31, 0x32, 0x33, 0x34, 0x35, 0x65, 0x2b, 0x33, 0x35, 0x09, 0x01, 0x01 // empty AmfArray }, d); }
AmfDouble AmfDouble::deserialize(v8::const_iterator& it, v8::const_iterator end, SerializationContext&) { if (it == end || *it++ != AMF_DOUBLE) throw std::invalid_argument("AmfDouble: Invalid type marker"); // Dates are always encoded as 64bit double in network order. if (end - it < 8) throw std::out_of_range("Not enough bytes for AmfDouble"); double v; std::copy(it, it + 8, reinterpret_cast<u8 *>(&v)); it += 8; return AmfDouble(ntoh(v)); }
TEST(DictionarySerializationTest, Clear) { AmfDictionary d(false, true); d.insert(AmfBool(true), AmfInteger(17)); d.clear(); isEqual(v8 { 0x11, 0x01, // no elements 0x01 // weak keys }, d); d.insert(AmfBool(false), AmfDouble(17.0)); isEqual(v8 { 0x11, 0x03, // 1 element 0x01, // weak keys 0x02, // AmfBool false 0x05, 0x40, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // AmfDouble 17.0 }, d); }
TEST(DeserializerTest, Double) { deserializesTo(AmfDouble(0.5), { 0x05, 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }); deserializesTo(AmfDouble(0.5), { 0x05, 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 3); }