Skip to content

Commit

Permalink
[Java] Using sinceVersion from field instead of type declaration
Browse files Browse the repository at this point in the history
  • Loading branch information
zyulyaev authored and Nikita Zyulyaev committed Mar 21, 2018
1 parent fee2a49 commit 1a03c40
Show file tree
Hide file tree
Showing 3 changed files with 186 additions and 122 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2410,7 +2410,7 @@ private CharSequence generateEnumDecoder(
indent + " }\n\n",
enumName,
propertyName,
generatePropertyNotPresentCondition(inComposite, DECODER, token.version(), indent),
generatePropertyNotPresentCondition(inComposite, DECODER, signalToken.version(), indent),
enumName,
generateGet(encoding.primitiveType(), "offset + " + token.offset(), byteOrderString(encoding)));
}
Expand Down Expand Up @@ -2468,7 +2468,7 @@ private CharSequence generateBitSetProperty(
generateFlyweightPropertyJavadoc(indent + INDENT, propertyToken, bitSetName),
bitSetName,
propertyName,
generatePropertyNotPresentCondition(inComposite, codecType, bitsetToken.version(), indent),
generatePropertyNotPresentCondition(inComposite, codecType, propertyToken.version(), indent),
propertyName,
bitsetToken.offset(),
propertyName));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,118 +64,174 @@ public void setup() throws Exception
public void testMessage1() throws Exception
{
final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]);
final Object encoder = wrap(buffer, compile("TestMessage1Encoder").newInstance());

set(encoder, "tag1", int.class, 100);
set(encoder, "tag2", int.class, 200);

final Object compositeEncoder = getACompositeEncoder(buffer, 8);
wrap(8, compositeEncoder, buffer, BUFFER_CLASS);

set(compositeEncoder, "value", int.class, 300);

final Object decoderVersion0 = getMessage1Decoder(buffer, 4, 0);
assertEquals(100, get(decoderVersion0, "tag1"));
assertEquals(Integer.MIN_VALUE, get(decoderVersion0, "tag2"));
assertNull(get(decoderVersion0, "tag3"));

assertEquals(0, decoderVersion0.getClass().getMethod("tag1SinceVersion").invoke(null));
assertEquals(1, decoderVersion0.getClass().getMethod("tag2SinceVersion").invoke(null));
assertEquals(3, decoderVersion0.getClass().getMethod("tag3SinceVersion").invoke(null));

final Object decoderVersion1 = getMessage1Decoder(buffer, 8, 1);
assertEquals(100, get(decoderVersion1, "tag1"));
assertEquals(200, get(decoderVersion1, "tag2"));
assertNull(get(decoderVersion1, "tag3"));

final Object decoderVersion2 = getMessage1Decoder(buffer, 8, 2);
assertEquals(100, get(decoderVersion2, "tag1"));
assertEquals(200, get(decoderVersion2, "tag2"));
assertNull(get(decoderVersion1, "tag3"));

final Object decoderVersion3 = getMessage1Decoder(buffer, 12, 3);
assertEquals(100, get(decoderVersion3, "tag1"));
assertEquals(200, get(decoderVersion3, "tag2"));
final Object compositeDecoder3 = get(decoderVersion3, "tag3");
assertNotNull(compositeDecoder3);
assertEquals(300, get(compositeDecoder3, "value"));

final Object decoderVersion4 = getMessage1Decoder(buffer, 12, 4);
assertEquals(100, get(decoderVersion4, "tag1"));
assertEquals(200, get(decoderVersion4, "tag2"));
final Object compositeDecoder4 = get(decoderVersion4, "tag3");
assertNotNull(compositeDecoder4);
assertEquals(300, get(compositeDecoder4, "value"));

{ // Encode
final Object encoder = wrap(buffer, compile("TestMessage1Encoder").newInstance());

set(encoder, "tag1", int.class, 100);
set(encoder, "tag2", int.class, 200);

final Object compositeEncoder = encoder.getClass().getMethod("tag3").invoke(encoder);
set(compositeEncoder, "value", int.class, 300);

final Object enumConstant = getAEnumConstant(encoder, "AEnum", 1);
set(encoder, "tag4", enumConstant.getClass(), enumConstant);

final Object setEncoder = encoder.getClass().getMethod("tag5").invoke(encoder);
set(setEncoder, "firstChoice", boolean.class, false);
set(setEncoder, "secondChoice", boolean.class, true);
}

{ // Decode version 0
final Object decoderVersion0 = getMessage1Decoder(buffer, 4, 0);
assertEquals(100, get(decoderVersion0, "tag1"));
assertEquals(Integer.MIN_VALUE, get(decoderVersion0, "tag2"));
assertNull(get(decoderVersion0, "tag3"));
assertNull(get(decoderVersion0, "tag4"));
assertNull(get(decoderVersion0, "tag5"));

assertEquals(0, decoderVersion0.getClass().getMethod("tag1SinceVersion").invoke(null));
assertEquals(1, decoderVersion0.getClass().getMethod("tag2SinceVersion").invoke(null));
assertEquals(2, decoderVersion0.getClass().getMethod("tag3SinceVersion").invoke(null));
assertEquals(3, decoderVersion0.getClass().getMethod("tag4SinceVersion").invoke(null));
assertEquals(4, decoderVersion0.getClass().getMethod("tag5SinceVersion").invoke(null));
}

{ // Decode version 1
final Object decoderVersion1 = getMessage1Decoder(buffer, 8, 1);
assertEquals(100, get(decoderVersion1, "tag1"));
assertEquals(200, get(decoderVersion1, "tag2"));
assertNull(get(decoderVersion1, "tag3"));
assertNull(get(decoderVersion1, "tag4"));
assertNull(get(decoderVersion1, "tag5"));
}

{ // Decode version 2
final Object decoderVersion2 = getMessage1Decoder(buffer, 8, 2);
assertEquals(100, get(decoderVersion2, "tag1"));
assertEquals(200, get(decoderVersion2, "tag2"));
final Object compositeDecoder2 = get(decoderVersion2, "tag3");
assertNotNull(compositeDecoder2);
assertEquals(300, get(compositeDecoder2, "value"));
assertNull(get(decoderVersion2, "tag4"));
assertNull(get(decoderVersion2, "tag5"));
}

{ // Decode version 3
final Object decoderVersion3 = getMessage1Decoder(buffer, 12, 3);
assertEquals(100, get(decoderVersion3, "tag1"));
assertEquals(200, get(decoderVersion3, "tag2"));
final Object compositeDecoder3 = get(decoderVersion3, "tag3");
assertNotNull(compositeDecoder3);
assertEquals(300, get(compositeDecoder3, "value"));
final Object enumConstant = getAEnumConstant(decoderVersion3, "AEnum", 1);
assertEquals(enumConstant, get(decoderVersion3, "tag4"));
assertNull(get(decoderVersion3, "tag5"));
}

{ // Decode version 4
final Object decoderVersion4 = getMessage1Decoder(buffer, 12, 4);
assertEquals(100, get(decoderVersion4, "tag1"));
assertEquals(200, get(decoderVersion4, "tag2"));
final Object compositeDecoder4 = get(decoderVersion4, "tag3");
assertNotNull(compositeDecoder4);
assertEquals(300, get(compositeDecoder4, "value"));
final Object enumConstant = getAEnumConstant(decoderVersion4, "AEnum", 1);
assertEquals(enumConstant, get(decoderVersion4, "tag4"));
final Object setDecoder = get(decoderVersion4, "tag5");
assertNotNull(setDecoder);
assertEquals(false, get(setDecoder, "firstChoice"));
assertEquals(true, get(setDecoder, "secondChoice"));
}
}

@Test
public void testMessage2() throws Exception
{
final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]);
final Object encoder = wrap(buffer, compile("TestMessage2Encoder").newInstance());

set(encoder, "tag1", int.class, 100);
set(encoder, "tag2", int.class, 200);

final Object compositeEncoder = getACompositeEncoder(buffer, 8);
set(compositeEncoder, "value", int.class, 300);

final Object decoderVersion0 = getMessage2Decoder(buffer, 4, 0);
assertEquals(100, get(decoderVersion0, "tag1"));
assertEquals(Integer.MIN_VALUE, get(decoderVersion0, "tag2"));
assertNull(get(decoderVersion0, "tag3"));

assertEquals(0, decoderVersion0.getClass().getMethod("tag1SinceVersion").invoke(null));
assertEquals(2, decoderVersion0.getClass().getMethod("tag2SinceVersion").invoke(null));
assertEquals(4, decoderVersion0.getClass().getMethod("tag3SinceVersion").invoke(null));

final Object decoderVersion1 = getMessage2Decoder(buffer, 4, 1);
assertEquals(100, get(decoderVersion1, "tag1"));
assertEquals(Integer.MIN_VALUE, get(decoderVersion1, "tag2"));
assertNull(get(decoderVersion1, "tag3"));

final Object decoderVersion2 = getMessage2Decoder(buffer, 8, 2);
assertEquals(100, get(decoderVersion2, "tag1"));
assertEquals(200, get(decoderVersion2, "tag2"));
assertNull(get(decoderVersion1, "tag3"));

final Object decoderVersion3 = getMessage2Decoder(buffer, 8, 3);
assertEquals(100, get(decoderVersion3, "tag1"));
assertEquals(200, get(decoderVersion3, "tag2"));
assertNull(get(decoderVersion1, "tag3"));

final Object decoderVersion4 = getMessage2Decoder(buffer, 12, 4);
assertEquals(100, get(decoderVersion4, "tag1"));
assertEquals(200, get(decoderVersion4, "tag2"));
final Object compositeDecoder4 = get(decoderVersion4, "tag3");
assertNotNull(compositeDecoder4);
assertEquals(300, get(compositeDecoder4, "value"));
}

@Test
public void testMessageHeader() throws Exception
{
final UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]);
final Object encoder = wrap(buffer, compile("MessageHeaderEncoder").newInstance());

set(encoder, "blockLength", int.class, 10);
set(encoder, "templateId", int.class, 1);
set(encoder, "schemaId", int.class, 1);
set(encoder, "version", int.class, 5);
set(encoder, "headerLength", int.class, 12);
set(encoder, "extraField", int.class, 100);

final Object decoder = compile("MessageHeaderDecoder").newInstance();
wrap(0, decoder, buffer, READ_ONLY_BUFFER_CLASS);

assertEquals(10, get(decoder, "blockLength"));
assertEquals(1, get(decoder, "templateId"));
assertEquals(1, get(decoder, "schemaId"));
assertEquals(5, get(decoder, "version"));
assertEquals(12, get(decoder, "headerLength"));
assertEquals(100, get(decoder, "extraField"));

assertEquals(5, decoder.getClass().getMethod("extraFieldSinceVersion").invoke(null));
{ // Encode
final Object encoder = wrap(buffer, compile("TestMessage2Encoder").newInstance());

set(encoder, "tag1", int.class, 100);
set(encoder, "tag2", int.class, 200);

final Object compositeEncoder = encoder.getClass().getMethod("tag3").invoke(encoder);
set(compositeEncoder, "value", int.class, 300);

final Object enumConstant = getAEnumConstant(encoder, "AEnum", 1);
set(encoder, "tag4", enumConstant.getClass(), enumConstant);

final Object setEncoder = encoder.getClass().getMethod("tag5").invoke(encoder);
set(setEncoder, "firstChoice", boolean.class, false);
set(setEncoder, "secondChoice", boolean.class, true);
}

{ // Decode version 0
final Object decoderVersion0 = getMessage2Decoder(buffer, 4, 0);
assertEquals(100, get(decoderVersion0, "tag1"));
assertEquals(Integer.MIN_VALUE, get(decoderVersion0, "tag2"));
assertNull(get(decoderVersion0, "tag3"));
assertNull(get(decoderVersion0, "tag4"));
assertNull(get(decoderVersion0, "tag5"));

assertEquals(0, decoderVersion0.getClass().getMethod("tag1SinceVersion").invoke(null));
assertEquals(2, decoderVersion0.getClass().getMethod("tag2SinceVersion").invoke(null));
assertEquals(1, decoderVersion0.getClass().getMethod("tag3SinceVersion").invoke(null));
assertEquals(4, decoderVersion0.getClass().getMethod("tag4SinceVersion").invoke(null));
assertEquals(3, decoderVersion0.getClass().getMethod("tag5SinceVersion").invoke(null));
}

{ // Decode version 1
final Object decoderVersion1 = getMessage2Decoder(buffer, 8, 1);
assertEquals(100, get(decoderVersion1, "tag1"));
assertEquals(Integer.MIN_VALUE, get(decoderVersion1, "tag2"));
final Object compositeDecoder2 = get(decoderVersion1, "tag3");
assertNotNull(compositeDecoder2);
assertEquals(300, get(compositeDecoder2, "value"));
assertNull(get(decoderVersion1, "tag4"));
assertNull(get(decoderVersion1, "tag5"));
}

{ // Decode version 2
final Object decoderVersion2 = getMessage2Decoder(buffer, 8, 2);
assertEquals(100, get(decoderVersion2, "tag1"));
assertEquals(200, get(decoderVersion2, "tag2"));
final Object compositeDecoder2 = get(decoderVersion2, "tag3");
assertNotNull(compositeDecoder2);
assertEquals(300, get(compositeDecoder2, "value"));
assertNull(get(decoderVersion2, "tag4"));
assertNull(get(decoderVersion2, "tag5"));
}

{ // Decode version 3
final Object decoderVersion3 = getMessage2Decoder(buffer, 12, 3);
assertEquals(100, get(decoderVersion3, "tag1"));
assertEquals(200, get(decoderVersion3, "tag2"));
final Object compositeDecoder3 = get(decoderVersion3, "tag3");
assertNotNull(compositeDecoder3);
assertEquals(300, get(compositeDecoder3, "value"));
assertNull(get(decoderVersion3, "tag4"));
final Object setDecoder = get(decoderVersion3, "tag5");
assertNotNull(setDecoder);
assertEquals(false, get(setDecoder, "firstChoice"));
assertEquals(true, get(setDecoder, "secondChoice"));
}

{ // Decode version 4
final Object decoderVersion4 = getMessage2Decoder(buffer, 12, 4);
assertEquals(100, get(decoderVersion4, "tag1"));
assertEquals(200, get(decoderVersion4, "tag2"));
final Object compositeDecoder4 = get(decoderVersion4, "tag3");
assertNotNull(compositeDecoder4);
assertEquals(300, get(compositeDecoder4, "value"));
final Object enumConstant = getAEnumConstant(decoderVersion4, "AEnum", 1);
assertEquals(enumConstant, get(decoderVersion4, "tag4"));
final Object setDecoder = get(decoderVersion4, "tag5");
assertNotNull(setDecoder);
assertEquals(false, get(setDecoder, "firstChoice"));
assertEquals(true, get(setDecoder, "secondChoice"));
}
}

private JavaGenerator generator()
Expand All @@ -197,11 +253,11 @@ private Object getMessage2Decoder(final UnsafeBuffer buffer, final int blockLeng
return wrap(buffer, decoder, blockLength, version);
}

private Object getACompositeEncoder(final UnsafeBuffer buffer, final int offset) throws Exception
private Object getAEnumConstant(
final Object flyweight, final String enumClassName, final int constantIndex) throws Exception
{
final Object encoder = compile("ACompositeEncoder").newInstance();
wrap(offset, encoder, buffer, BUFFER_CLASS);
return encoder;
final String fqClassName = ir.applicableNamespace() + "." + enumClassName;
return flyweight.getClass().getClassLoader().loadClass(fqClassName).getEnumConstants()[constantIndex];
}

private Class<?> compile(final String className) throws Exception
Expand Down
30 changes: 19 additions & 11 deletions sbe-tool/src/test/resources/extension-schema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,43 @@
<type name="templateId" primitiveType="uint16"/>
<type name="schemaId" primitiveType="uint16"/>
<type name="version" primitiveType="uint16"/>
<type name="headerLength" primitiveType="uint16"/>

<type name="extraField" primitiveType="int32" sinceVersion="5"/>
</composite>
<composite name="groupSizeEncoding" description="Repeating group dimensions">
<type name="blockLength" primitiveType="uint16"/>
<type name="numInGroup" primitiveType="uint8" semanticType="NumInGroup"/>
</composite>
<type name="AType" primitiveType="int32" sinceVersion="1"/>
<composite name="AComposite" sinceVersion="3">
<composite name="AComposite" sinceVersion="1">
<type name="value" primitiveType="int32"/>
</composite>
<enum name="AEnum" encodingType="uint8" sinceVersion="3">
<validValue name="FirstValue">0</validValue>
<validValue name="SecondValue">1</validValue>
</enum>
<set name="ASet" encodingType="uint8" sinceVersion="3">
<choice name="FirstChoice">0</choice>
<choice name="SecondChoice">1</choice>
</set>
</types>
<!--
Version 0: schema created
Version 1: aType introduced and tag2 added to TestMessage1
Version 2: tag2 added to TestMessage2
Version 3: aComposite introduced and tag3 added to TestMessage1
Version 4: tag3 added to TestMessage2
Version 5: extraField is added to messageHeader
Version 1: AType, AComposite introduced; tag2 added to TestMessage1, tag3 added to TestMessage2
Version 2: tag3 added to TestMessage1, tag2 added to TestMessage2
Version 3: AEnum, ASet introduced; tag4 added to TestMessage1, tag5 added to TestMessage2
Version 4: tag5 added to TestMessage1, tag4 added to TestMessage2
-->
<sbe:message name="TestMessage1" id="1">
<field name="tag1" id="1" type="int32"/>
<field name="tag2" id="2" type="AType" sinceVersion="1"/>
<field name="tag3" id="3" type="AComposite" sinceVersion="3"/>
<field name="tag3" id="3" type="AComposite" sinceVersion="2"/>
<field name="tag4" id="4" type="AEnum" sinceVersion="3"/>
<field name="tag5" id="5" type="ASet" sinceVersion="4"/>
</sbe:message>
<sbe:message name="TestMessage2" id="2">
<field name="tag1" id="1" type="int32"/>
<field name="tag3" id="3" type="AComposite" sinceVersion="1"/>
<field name="tag2" id="2" type="AType" sinceVersion="2"/>
<field name="tag3" id="3" type="AComposite" sinceVersion="4"/>
<field name="tag5" id="5" type="ASet" sinceVersion="3"/>
<field name="tag4" id="4" type="AEnum" sinceVersion="4"/>
</sbe:message>
</sbe:messageSchema>

0 comments on commit 1a03c40

Please sign in to comment.