package org.opendaylight.yangtools.yang.data.codec.gson;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import com.google.common.collect.ImmutableSet;
import com.google.gson.stream.JsonWriter;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
-@ExtendWith(MockitoExtension.class)
-public class YT1473Test {
-
+class YT1473Test {
private static final String FOO_NS = "foons"; // namespace for prefix 'foo'
private static final QName FOO_FOO = QName.create(FOO_NS, "foo"); // list with key 'str'
private static final QName FOO_BAR = QName.create(FOO_NS, "bar"); // list with key 'qname'
private static final QName FOO_BAZ = QName.create(FOO_NS, "baz"); // list with key 'id'
+ private static final QName FOO_BEE = QName.create(FOO_NS, "bee"); // list with key 'bts'
private static final QName FOO_ONE = QName.create(FOO_NS, "one"); // identity
private static final QName FOO_STR = QName.create(FOO_NS, "str"); // key of type 'string'
private static final QName FOO_QNAME = QName.create(FOO_NS, "qname"); // key of type 'one' based
private static final QName FOO_ID = QName.create(FOO_NS, "id"); // key of type 'instance-identifier'
+ private static final QName FOO_BTS = QName.create(FOO_NS, "bts"); // key of type 'bts' (bits)
private static final String BAR_NS = "barns"; // namespace for prefix 'bar'
- private static final QName BAR_FOO = QName.create(BAR_NS, "foo"); // leaf of type 'foo:one' based
- private static final QName BAR_BAR = QName.create(BAR_NS, "bar"); // leaf of type 'instance-identifier'
+ private static final QName BAR_STR = QName.create(BAR_NS, "str"); // leaf-list of type 'string'
+ private static final QName BAR_FOO = QName.create(BAR_NS, "foo"); // leaf-list of type 'foo:one' based
+ private static final QName BAR_BAR = QName.create(BAR_NS, "bar"); // leaf-list of type 'instance-identifier'
+ private static final QName BAR_BEE = QName.create(BAR_NS, "bee"); // leaf-list of type 'foo:bts' (bits)
private static final QName BAR_TWO = QName.create(BAR_NS, "two"); // identity inheriting 'foo:one'
private static JSONCodec<YangInstanceIdentifier> CODEC;
- @Mock
- private JsonWriter writer;
- @Captor
- private ArgumentCaptor<String> captor;
-
@BeforeAll
- public static void beforeAll() {
+ static void beforeAll() {
final var modelContext = YangParserTestUtils.parseYangResourceDirectory("/yt1473");
- final var baz = modelContext.getDataChildByName(FOO_BAZ);
- assertTrue(baz instanceof ListSchemaNode);
- final var id = ((ListSchemaNode) baz).getDataChildByName(FOO_ID);
- assertTrue(id instanceof LeafSchemaNode);
- final var type = ((LeafSchemaNode) id).getType();
- assertTrue(type instanceof InstanceIdentifierTypeDefinition);
- CODEC = JSONCodecFactorySupplier.RFC7951.getShared(modelContext)
- .instanceIdentifierCodec((InstanceIdentifierTypeDefinition) type);
+ final var baz = assertInstanceOf(ListSchemaNode.class, modelContext.getDataChildByName(FOO_BAZ));
+ final var id = assertInstanceOf(LeafSchemaNode.class, baz.getDataChildByName(FOO_ID));
+ final var type = assertInstanceOf(InstanceIdentifierTypeDefinition.class, id.getType());
+ CODEC = JSONCodecFactorySupplier.RFC7951.getShared(modelContext).instanceIdentifierCodec(type);
}
@AfterAll
- public static void afterAll() {
+ static void afterAll() {
CODEC = null;
}
@Test
- public void testSerializeSimple() throws Exception {
+ void testSerializeSimple() throws Exception {
// No escaping needed, use single quotes
- assertEquals("/foo:foo[str='str\"']", write(buildYangInstanceIdentifier(FOO_FOO, FOO_STR, "str\"")));
+ assertSerdes("/bar:str[.='str\"']", buildYangInstanceIdentifier(BAR_STR, "str\""));
+ assertSerdes("/bar:str[.='str\\']", buildYangInstanceIdentifier(BAR_STR, "str\\"));
+ assertSerdes("/bar:str[.='str\r']", buildYangInstanceIdentifier(BAR_STR, "str\r"));
+ assertSerdes("/bar:str[.='str\n']", buildYangInstanceIdentifier(BAR_STR, "str\n"));
+ assertSerdes("/bar:str[.='str\t']", buildYangInstanceIdentifier(BAR_STR, "str\t"));
+
+ assertSerdes("/foo:foo[str='str\"\\']", buildYangInstanceIdentifier(FOO_FOO, FOO_STR, "str\"\\"));
+ assertSerdes("/foo:foo[str='str\r\n\t']", buildYangInstanceIdentifier(FOO_FOO, FOO_STR, "str\r\n\t"));
}
@Test
- @Disabled("YT-1473: string escaping needs to work")
- public void testSerializeEscaped() throws Exception {
+ void testSerializeEscaped() throws Exception {
// Escaping is needed, use double quotes and escape
- assertEquals("/foo:foo[str=\"str'\\\"\"]", write(buildYangInstanceIdentifier(FOO_FOO, FOO_STR, "str'\"")));
+ assertSerdes("/bar:str[.=\"str'\\\"\"]", buildYangInstanceIdentifier(BAR_STR, "str'\""));
+ assertSerdes("/bar:str[.=\"str'\\n\"]", buildYangInstanceIdentifier(BAR_STR, "str'\n"));
+ assertSerdes("/bar:str[.=\"str'\\t\"]", buildYangInstanceIdentifier(BAR_STR, "str'\t"));
+ assertSerdes("/bar:str[.=\"str'\r\"]", buildYangInstanceIdentifier(BAR_STR, "str'\r"));
+
+ assertSerdes("/foo:foo[str=\"str'\\\"\\n\"]", buildYangInstanceIdentifier(FOO_FOO, FOO_STR, "str'\"\n"));
+ assertSerdes("/foo:foo[str=\"str'\\t\r\"]", buildYangInstanceIdentifier(FOO_FOO, FOO_STR, "str'\t\r"));
}
@Test
@Disabled("YT-1473: QName values need to be recognized and properly encoded via identity codec")
- public void testSerializeIdentityRefSame() throws Exception {
- // TODO: an improvement is to use just 'one' as the namespace is the same as the leaf (see RFC7951 section 6.8)
- assertEquals("/foo:bar[foo:qname='foo:one']", write(buildYangInstanceIdentifier(FOO_BAR, FOO_QNAME, FOO_ONE)));
+ void testSerializeIdentityRefSame() throws Exception {
+ assertSerdes("/foo:bar[qname='one']", buildYangInstanceIdentifier(FOO_BAR, FOO_QNAME, FOO_ONE));
}
@Test
@Disabled("YT-1473: QName values need to be recognized and properly encoded via identity codec")
- public void testSerializeIdentityRefOther() throws Exception {
+ void testSerializeIdentityRefOther() throws Exception {
// No escaping is needed, use double quotes and escape
- assertEquals("/foo:bar[qname='bar:two']", write(buildYangInstanceIdentifier(FOO_BAR, FOO_QNAME, BAR_TWO)));
+ assertSerdes("/foo:bar[qname='bar:two']", buildYangInstanceIdentifier(FOO_BAR, FOO_QNAME, BAR_TWO));
}
@Test
@Disabled("YT-1473: Instance-identifier values need to be recognized and properly encoded and escaped")
- public void testSerializeInstanceIdentifierRef() throws Exception {
- assertEquals("/foo:baz[id=\"/foo:bar[qname='bar:two']\"]", write(
- buildYangInstanceIdentifier(FOO_BAZ, FOO_ID, buildYangInstanceIdentifier(FOO_BAR, FOO_QNAME, BAR_TWO)))
- );
+ void testSerializeInstanceIdentifierRef() throws Exception {
+ assertSerdes("/foo:baz[id=\"/foo:bar[qname='bar:two']\"]",
+ buildYangInstanceIdentifier(FOO_BAZ, FOO_ID, buildYangInstanceIdentifier(FOO_BAR, FOO_QNAME, BAR_TWO)));
}
@Test
@Disabled("YT-1473: QName values need to be recognized and properly encoded via identity codec")
- public void testSerializeIdentityValue() throws Exception {
- assertEquals("/bar:foo[.='foo:one']", write(buildYangInstanceIdentifier(BAR_FOO, FOO_ONE)));
+ void testSerializeIdentityValue() throws Exception {
+ assertSerdes("/bar:foo[.='foo:one']", buildYangInstanceIdentifier(BAR_FOO, FOO_ONE));
+ assertSerdes("/bar:foo[.='two']", buildYangInstanceIdentifier(BAR_FOO, BAR_TWO));
}
@Test
@Disabled("YT-1473: Instance-identifier values need to be recognized and properly encoded and escaped")
- public void testSerializeInstanceIdentifierValue() throws Exception {
- assertEquals("/bar:bar[.=\"/foo:bar/bar[qname='bar:two'\"]']",
- write(buildYangInstanceIdentifier(BAR_BAR, buildYangInstanceIdentifier(FOO_BAR, FOO_QNAME, BAR_TWO))));
+ void testSerializeInstanceIdentifierValue() throws Exception {
+ assertSerdes("/bar:bar[.=\"/foo:bar[qname='bar:two']\"]",
+ buildYangInstanceIdentifier(BAR_BAR, buildYangInstanceIdentifier(FOO_BAR, FOO_QNAME, BAR_TWO)));
+ assertSerdes("/bar:bar[.=\"/foo:bar[qname='one']\"]",
+ buildYangInstanceIdentifier(BAR_BAR, buildYangInstanceIdentifier(FOO_BAR, FOO_QNAME, FOO_ONE)));
}
- private static YangInstanceIdentifier buildYangInstanceIdentifier(final QName node, final QName key,
- final Object value) {
- return YangInstanceIdentifier.create(
- new NodeIdentifier(node), NodeIdentifierWithPredicates.of(node, key, value));
+ @Test
+ @Disabled("YT-1473: bits values need to be recognized and properly encoded")
+ void testSerializeBits() throws Exception {
+ assertSerdes("/foo:bee[bts='']", buildYangInstanceIdentifier(FOO_BEE, FOO_BTS, ImmutableSet.of()));
+ assertSerdes("/foo:bee[bts='one']", buildYangInstanceIdentifier(FOO_BEE, FOO_BTS, ImmutableSet.of("one")));
+ assertSerdes("/foo:bee[bts='two three']",
+ buildYangInstanceIdentifier(FOO_BEE, FOO_BTS, ImmutableSet.of("two", "three")));
}
- private static YangInstanceIdentifier buildYangInstanceIdentifier(final QName nodeQName, final Object value) {
- return YangInstanceIdentifier.create(new NodeWithValue<>(nodeQName, value));
+ @Test
+ @Disabled("YT-1473: bits values need to be recognized and properly encoded")
+ void testSerializeBitsValue() throws Exception {
+ assertSerdes("/bar:bee[.='']", buildYangInstanceIdentifier(BAR_BEE, ImmutableSet.of()));
+ assertSerdes("/bar:bee[.='one']", buildYangInstanceIdentifier(BAR_BEE, ImmutableSet.of("one")));
+ assertSerdes("/bar:bee[.='two three']", buildYangInstanceIdentifier(BAR_BEE, ImmutableSet.of("two", "three")));
}
- private String write(final YangInstanceIdentifier yangInstanceIdentifier) throws Exception {
+ private static void assertSerdes(final String expected, final YangInstanceIdentifier id) throws Exception {
+ final var writer = mock(JsonWriter.class);
+ final var captor = ArgumentCaptor.forClass(String.class);
doReturn(writer).when(writer).value(anyString());
- CODEC.writeValue(writer, yangInstanceIdentifier);
+ CODEC.writeValue(writer, id);
verify(writer).value(captor.capture());
- return captor.getValue();
+
+ assertEquals(expected, captor.getValue());
+ assertEquals(id, CODEC.parseValue(null, expected));
+ }
+
+ private static YangInstanceIdentifier buildYangInstanceIdentifier(final QName node, final QName key,
+ final Object value) {
+ return YangInstanceIdentifier.create(
+ new NodeIdentifier(node), NodeIdentifierWithPredicates.of(node, key, value));
+ }
+
+ private static YangInstanceIdentifier buildYangInstanceIdentifier(final QName node, final Object value) {
+ return YangInstanceIdentifier.create(new NodeIdentifier(node), new NodeWithValue<>(node, value));
}
}