import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
-import com.google.common.collect.ImmutableClassToInstanceMap;
import java.net.URI;
+import java.util.List;
import java.util.UUID;
import org.eclipse.jdt.annotation.Nullable;
import org.junit.jupiter.api.BeforeEach;
import org.opendaylight.mdsal.common.api.CommitInfo;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.mdsal.dom.api.DOMDataBroker;
-import org.opendaylight.mdsal.dom.api.DOMDataTreeChangeService;
+import org.opendaylight.mdsal.dom.api.DOMDataBroker.DataTreeChangeExtension;
import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
-import org.opendaylight.restconf.nb.rfc8040.databind.DatabindContext;
+import org.opendaylight.restconf.server.api.DatabindContext;
+import org.opendaylight.restconf.server.api.DatabindPath;
import org.opendaylight.restconf.server.mdsal.MdsalRestconfStreamRegistry;
import org.opendaylight.restconf.server.spi.DatabindProvider;
import org.opendaylight.restconf.server.spi.OperationInput;
+import org.opendaylight.restconf.server.testlib.CompletingServerRequest;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.monitoring.rev170126.restconf.state.streams.stream.Access;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.remote.rev140114.CreateDataChangeEventSubscription;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.remote.rev140114.CreateDataChangeEventSubscriptionOutput;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
-import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.stmt.RpcEffectiveStatement;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
@ExtendWith(MockitoExtension.class)
class CreateNotificationStreamRpcTest {
private static final EffectiveModelContext SCHEMA_CTX = YangParserTestUtils.parseYangResourceDirectory("/streams");
- private static final URI RESTCONF_URI = URI.create("/rests");
+ private static final URI RESTCONF_URI = URI.create("/rests/");
private static final YangInstanceIdentifier TOASTER = YangInstanceIdentifier.of(
QName.create("http://netconfcentral.org/ns/toaster", "2009-11-20", "toaster"));
+ private final CompletingServerRequest<ContainerNode> request = new CompletingServerRequest<>();
+
@Mock
private DOMDataBroker dataBroker;
@Mock
- private DOMDataTreeChangeService treeChange;
+ private DataTreeChangeExtension treeChange;
@Mock
private DOMDataTreeWriteTransaction tx;
@Captor
public void before() {
databindProvider = () -> DatabindContext.ofModel(SCHEMA_CTX);
- doReturn(ImmutableClassToInstanceMap.of(DOMDataTreeChangeService.class, treeChange))
- .when(dataBroker).getExtensions();
+ doReturn(List.of(treeChange)).when(dataBroker).supportedExtensions();
+ doCallRealMethod().when(dataBroker).extension(any());
rpc = new CreateDataChangeEventSubscriptionRpc(new MdsalRestconfStreamRegistry(dataBroker), databindProvider,
dataBroker);
}
@Test
- void createStreamTest() {
+ void createStreamTest() throws Exception {
doReturn(tx).when(dataBroker).newWriteOnlyTransaction();
doNothing().when(tx).put(eq(LogicalDatastoreType.OPERATIONAL), pathCaptor.capture(), dataCaptor.capture());
doReturn(CommitInfo.emptyFluentFuture()).when(tx).commit();
- final var output = assertInstanceOf(ContainerNode.class, rpc.invoke(RESTCONF_URI, createInput("path", TOASTER))
- .getOrThrow().output());
+ rpc.invoke(request, RESTCONF_URI, createInput("path", TOASTER));
+ final var output = request.getResult();
assertEquals(new NodeIdentifier(CreateDataChangeEventSubscriptionOutput.QNAME), output.name());
assertEquals(1, output.size());
new NodeIdentifier(QName.create(rcStream, "streams")),
new NodeIdentifier(rcStream),
streamId), pathCaptor.getValue());
- assertEquals(Builders.mapEntryBuilder()
+ assertEquals(ImmutableNodes.newMapEntryBuilder()
.withNodeIdentifier(streamId)
.withChild(ImmutableNodes.leafNode(rcName, name))
.withChild(ImmutableNodes.leafNode(QName.create(rcStream, "description"),
"Events occuring in CONFIGURATION datastore under /toaster:toaster"))
- .withChild(Builders.mapBuilder()
+ .withChild(ImmutableNodes.newSystemMapBuilder()
.withNodeIdentifier(new NodeIdentifier(Access.QNAME))
- .withChild(Builders.mapEntryBuilder()
+ .withChild(ImmutableNodes.newMapEntryBuilder()
.withNodeIdentifier(NodeIdentifierWithPredicates.of(Access.QNAME, rcEncoding, "json"))
.withChild(ImmutableNodes.leafNode(rcEncoding, "json"))
.withChild(ImmutableNodes.leafNode(rcLocation, "/rests/streams/json/" + name))
.build())
- .withChild(Builders.mapEntryBuilder()
+ .withChild(ImmutableNodes.newMapEntryBuilder()
.withNodeIdentifier(NodeIdentifierWithPredicates.of(Access.QNAME, rcEncoding, "xml"))
.withChild(ImmutableNodes.leafNode(rcEncoding, "xml"))
.withChild(ImmutableNodes.leafNode(rcLocation, "/rests/streams/xml/" + name))
@Test
void createStreamWrongValueTest() {
- final var payload = createInput("path", "String value");
- final var ex = assertThrows(IllegalArgumentException.class, () -> rpc.invoke(RESTCONF_URI, payload));
+ rpc.invoke(request, RESTCONF_URI, createInput("path", "String value"));
+
+ final var ex = assertThrows(RestconfDocumentedException.class, request::getResult);
+ final var errors = ex.getErrors();
+ assertEquals(1, errors.size());
+ final var error = errors.get(0);
+ assertEquals(ErrorType.APPLICATION, error.getErrorType());
+ assertEquals(ErrorTag.BAD_ELEMENT, error.getErrorTag());
assertEquals("""
Bad child leafNode (urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote@2014-01-14)path = \
"String value"\
- """, ex.getMessage());
+ """, error.getErrorMessage());
}
@Test
void createStreamWrongInputRpcTest() {
- final var future = rpc.invoke(RESTCONF_URI, createInput(null, null));
- final var errors = assertThrows(RestconfDocumentedException.class, future::getOrThrow).getErrors();
+ rpc.invoke(request, RESTCONF_URI, createInput(null, null));
+
+ final var ex = assertThrows(RestconfDocumentedException.class, request::getResult);
+ final var errors = ex.getErrors();
assertEquals(1, errors.size());
final var error = errors.get(0);
assertEquals(ErrorType.APPLICATION, error.getErrorType());
stack.enterSchemaTree(CreateDataChangeEventSubscription.QNAME));
final var inference = stack.toInference();
- final var builder = Builders.containerBuilder()
+ final var builder = ImmutableNodes.newContainerBuilder()
.withNodeIdentifier(new NodeIdentifier(rpcStmt.input().argument()));
if (leafName != null) {
final var lfQName = QName.create(rpcStmt.argument(), leafName);
stack.enterDataTree(lfQName);
builder.withChild(ImmutableNodes.leafNode(lfQName, leafValue));
}
- return new OperationInput(databindProvider.currentContext(), inference, builder.build());
+ return new OperationInput(new DatabindPath.Rpc(databindProvider.currentDatabind(), inference, rpcStmt),
+ builder.build());
}
}