2 * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netconf.client.mdsal.impl;
10 import static org.junit.jupiter.api.Assertions.assertEquals;
11 import static org.junit.jupiter.api.Assertions.assertSame;
12 import static org.mockito.ArgumentMatchers.any;
13 import static org.mockito.ArgumentMatchers.anyCollection;
14 import static org.mockito.ArgumentMatchers.eq;
15 import static org.mockito.Mockito.doAnswer;
16 import static org.mockito.Mockito.doReturn;
17 import static org.mockito.Mockito.times;
18 import static org.mockito.Mockito.verify;
20 import com.google.common.util.concurrent.Futures;
21 import java.net.InetSocketAddress;
22 import java.util.Collection;
23 import java.util.List;
25 import org.junit.jupiter.api.Test;
26 import org.junit.jupiter.api.extension.ExtendWith;
27 import org.mockito.ArgumentCaptor;
28 import org.mockito.Mock;
29 import org.mockito.junit.jupiter.MockitoExtension;
30 import org.opendaylight.netconf.client.mdsal.AbstractTestModelTest;
31 import org.opendaylight.netconf.client.mdsal.api.NetconfSessionPreferences;
32 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceId;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.connection.oper.available.capabilities.AvailableCapability.CapabilityOrigin;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.connection.oper.available.capabilities.AvailableCapabilityBuilder;
35 import org.opendaylight.yangtools.yang.common.QName;
36 import org.opendaylight.yangtools.yang.model.api.source.SourceIdentifier;
37 import org.opendaylight.yangtools.yang.model.api.source.YangTextSource;
38 import org.opendaylight.yangtools.yang.model.repo.api.EffectiveModelContextFactory;
39 import org.opendaylight.yangtools.yang.model.repo.api.MissingSchemaSourceException;
40 import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
41 import org.opendaylight.yangtools.yang.model.repo.api.SchemaResolutionException;
42 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
44 @ExtendWith(MockitoExtension.class)
45 class SchemaSetupTest extends AbstractTestModelTest {
46 private static final RemoteDeviceId DEVICE_ID = new RemoteDeviceId("someDevice", new InetSocketAddress(42));
47 private static final String TEST_NAMESPACE = "test:namespace";
48 private static final String TEST_MODULE = "test-module";
49 private static final String TEST_REVISION = "2013-07-22";
50 private static final SourceIdentifier TEST_SID = new SourceIdentifier(TEST_MODULE, TEST_REVISION);
51 private static final SourceIdentifier TEST_SID2 = new SourceIdentifier(TEST_MODULE + "2", TEST_REVISION);
52 private static final QName TEST_QNAME = QName.create(TEST_NAMESPACE, TEST_REVISION, TEST_MODULE);
53 private static final QName TEST_QNAME2 = QName.create(TEST_NAMESPACE, TEST_REVISION, TEST_MODULE + "2");
56 private EffectiveModelContextFactory contextFactory;
58 private SchemaRepository schemaRepository;
60 private SchemaSourceProvider<YangTextSource> sourceProvider;
62 private YangTextSource source;
65 void testNetconfDeviceFlawedModelFailedResolution() throws Exception {
66 final var ex = new SchemaResolutionException("fail first", TEST_SID, new Throwable("YangTools parser fail"));
67 doAnswer(invocation -> invocation.getArgument(0, Collection.class).size() == 2
68 ? Futures.immediateFailedFuture(ex) : Futures.immediateFuture(SCHEMA_CONTEXT))
69 .when(contextFactory).createEffectiveModelContext(anyCollection());
71 doReturn(Futures.immediateFuture(source)).when(schemaRepository)
72 .getSchemaSource(any(), eq(YangTextSource.class));
74 final var setup = new SchemaSetup(schemaRepository, contextFactory, DEVICE_ID,
75 new DeviceSources(Set.of(TEST_QNAME, TEST_QNAME2), Set.of(TEST_QNAME, TEST_QNAME2), sourceProvider),
76 NetconfSessionPreferences.fromStrings(Set.of()));
78 final var result = Futures.getDone(setup.startResolution());
79 verify(contextFactory, times(2)).createEffectiveModelContext(anyCollection());
80 assertSame(SCHEMA_CONTEXT, result.modelContext());
84 void testNetconfDeviceMissingSource() throws Exception {
85 // Make fallback attempt to fail due to empty resolved sources
86 final var ex = new MissingSchemaSourceException(TEST_SID, "fail first");
87 doReturn(Futures.immediateFailedFuture(ex))
88 .when(schemaRepository).getSchemaSource(TEST_SID, YangTextSource.class);
89 doReturn(Futures.immediateFuture(source)).when(schemaRepository)
90 .getSchemaSource(TEST_SID2, YangTextSource.class);
91 doReturn(Futures.immediateFuture(SCHEMA_CONTEXT)).when(contextFactory)
92 .createEffectiveModelContext(anyCollection());
94 final var setup = new SchemaSetup(schemaRepository, contextFactory, DEVICE_ID,
95 new DeviceSources(Set.of(TEST_QNAME, TEST_QNAME2), Set.of(TEST_QNAME, TEST_QNAME2), sourceProvider),
96 NetconfSessionPreferences.fromStrings(Set.of()));
98 final var result = Futures.getDone(setup.startResolution());
99 final var captor = ArgumentCaptor.forClass(Collection.class);
100 verify(contextFactory).createEffectiveModelContext(captor.capture());
101 assertEquals(List.of(TEST_SID2), captor.getValue());
102 assertSame(SCHEMA_CONTEXT, result.modelContext());
106 void testNetconfDeviceNotificationsCapabilityIsNotPresent() throws Exception {
107 doReturn(Futures.immediateFuture(source)).when(schemaRepository)
108 .getSchemaSource(any(), eq(YangTextSource.class));
109 doReturn(Futures.immediateFuture(SCHEMA_CONTEXT)).when(contextFactory)
110 .createEffectiveModelContext(anyCollection());
112 final var setup = new SchemaSetup(schemaRepository, contextFactory, DEVICE_ID,
113 new DeviceSources(Set.of(TEST_QNAME), Set.of(TEST_QNAME), sourceProvider),
114 NetconfSessionPreferences.fromStrings(
115 Set.of(TEST_NAMESPACE + "?module=" + TEST_MODULE + "&revision=" + TEST_REVISION)));
117 final var result = Futures.getDone(setup.startResolution());
118 assertEquals(Set.of(new AvailableCapabilityBuilder()
119 .setCapability("(test:namespace?revision=2013-07-22)test-module")
120 .setCapabilityOrigin(CapabilityOrigin.DeviceAdvertised)
121 .build()), result.capabilities().resolvedCapabilities());