1 package org.opendaylight.controller.sal.binding.test;
3 import static org.junit.Assert.*;
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.HashMap;
11 import javassist.ClassPool;
13 import org.junit.Before;
14 import org.junit.Test;
16 import static org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper.*;
18 import org.opendaylight.controller.sal.binding.api.NotificationListener;
19 import org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator;
20 import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory;
21 import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory.NotificationInvoker;
22 import org.opendaylight.controller.sal.binding.spi.RpcRouter;
23 import org.opendaylight.controller.sal.binding.spi.RpcRoutingTable;
24 import org.opendaylight.controller.sal.binding.test.mock.BarListener;
25 import org.opendaylight.controller.sal.binding.test.mock.BarUpdate;
26 import org.opendaylight.controller.sal.binding.test.mock.CompositeListener;
27 import org.opendaylight.controller.sal.binding.test.mock.FlowDelete;
28 import org.opendaylight.controller.sal.binding.test.mock.FooListener;
29 import org.opendaylight.controller.sal.binding.test.mock.FooService;
30 import org.opendaylight.controller.sal.binding.test.mock.FooUpdate;
31 import org.opendaylight.controller.sal.binding.test.mock.InheritedContextInput;
32 import org.opendaylight.controller.sal.binding.test.mock.ReferencableObject;
33 import org.opendaylight.controller.sal.binding.test.mock.ReferencableObjectKey;
34 import org.opendaylight.controller.sal.binding.test.mock.SimpleInput;
35 import org.opendaylight.yangtools.yang.binding.Augmentation;
36 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
37 import org.opendaylight.yangtools.yang.binding.DataContainer;
38 import org.opendaylight.yangtools.yang.binding.DataObject;
39 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
40 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
41 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
43 import static org.mockito.Mockito.*;
45 public class RuntimeCodeGeneratorTest {
47 private RuntimeCodeGenerator codeGenerator;
48 private NotificationInvokerFactory invokerFactory;
51 public void initialize() {
52 this.codeGenerator = new RuntimeCodeGenerator(ClassPool.getDefault());
53 this.invokerFactory = codeGenerator.getInvokerFactory();
57 public void testGenerateDirectProxy() {
58 FooService product = codeGenerator.getDirectProxyFor(FooService.class);
59 assertNotNull(product);
63 public void testGenerateRouter() throws Exception {
64 RpcRouter<FooService> product = codeGenerator.getRouterFor(FooService.class);
65 assertNotNull(product);
66 assertNotNull(product.getInvocationProxy());
68 assertNotNull(product.getSupportedInputs());
69 assertTrue(product.getSupportedInputs().contains(SimpleInput.class));
70 assertTrue(product.getSupportedInputs().contains(InheritedContextInput.class));
71 assertEquals("2 fields should be generated.", 2, product.getInvocationProxy().getClass().getFields().length);
73 verifyRouting(product);
77 public void testInvoker() throws Exception {
79 FooListenerImpl fooListener = new FooListenerImpl();
81 NotificationInvoker invokerFoo = invokerFactory.invokerFor(fooListener);
84 assertSame(fooListener,invokerFoo.getDelegate());
85 assertNotNull(invokerFoo.getSupportedNotifications());
86 assertEquals(1, invokerFoo.getSupportedNotifications().size());
87 assertNotNull(invokerFoo.getInvocationProxy());
89 FooUpdateImpl fooOne = new FooUpdateImpl();
90 invokerFoo.getInvocationProxy().onNotification(fooOne);
92 assertEquals(1, fooListener.receivedFoos.size());
93 assertSame(fooOne, fooListener.receivedFoos.get(0));
95 CompositeListenerImpl composite = new CompositeListenerImpl();
97 NotificationInvoker invokerComposite = invokerFactory.invokerFor(composite);
99 assertNotNull(invokerComposite.getSupportedNotifications());
100 assertEquals(3, invokerComposite.getSupportedNotifications().size());
101 assertNotNull(invokerComposite.getInvocationProxy());
103 invokerComposite.getInvocationProxy().onNotification(fooOne);
105 assertEquals(1, composite.receivedFoos.size());
106 assertSame(fooOne, composite.receivedFoos.get(0));
108 assertEquals(0, composite.receivedBars.size());
110 BarUpdateImpl barOne = new BarUpdateImpl();
112 invokerComposite.getInvocationProxy().onNotification(barOne);
114 assertEquals(1, composite.receivedFoos.size());
115 assertEquals(1, composite.receivedBars.size());
116 assertSame(barOne, composite.receivedBars.get(0));
120 private void verifyRouting(RpcRouter<FooService> product) {
121 assertNotNull("Routing table should be initialized", product.getRoutingTable(BaseIdentity.class));
123 RpcRoutingTable<BaseIdentity, FooService> routingTable = product.getRoutingTable(BaseIdentity.class);
125 int servicesCount = 2;
126 int instancesPerService = 3;
128 InstanceIdentifier<?>[][] identifiers = identifiers(servicesCount, instancesPerService);
129 FooService service[] = new FooService[] { mock(FooService.class, "Instance 0"),
130 mock(FooService.class, "Instance 1") };
132 for (int i = 0; i < service.length; i++) {
133 for (InstanceIdentifier<?> instance : identifiers[i]) {
134 routingTable.updateRoute(instance, service[i]);
138 assertEquals("All instances should be registered.", servicesCount * instancesPerService, routingTable
139 .getRoutes().size());
141 SimpleInput[] instance_0_input = new SimpleInputImpl[] { new SimpleInputImpl(identifiers[0][0]),
142 new SimpleInputImpl(identifiers[0][1]), new SimpleInputImpl(identifiers[0][2]) };
144 SimpleInput[] instance_1_input = new SimpleInputImpl[] { new SimpleInputImpl(identifiers[1][0]),
145 new SimpleInputImpl(identifiers[1][1]), new SimpleInputImpl(identifiers[1][2]) };
147 // We test sending mock messages
149 product.getInvocationProxy().simple(instance_0_input[0]);
150 verify(service[0]).simple(instance_0_input[0]);
152 product.getInvocationProxy().simple(instance_0_input[1]);
153 product.getInvocationProxy().simple(instance_0_input[2]);
155 verify(service[0]).simple(instance_0_input[1]);
156 verify(service[0]).simple(instance_0_input[2]);
158 product.getInvocationProxy().simple(instance_1_input[0]);
160 // We should have call to instance 1
161 verify(service[1]).simple(instance_1_input[0]);
164 private InstanceIdentifier<?>[][] identifiers(int serviceSize, int instancesPerService) {
165 InstanceIdentifier<?>[][] ret = new InstanceIdentifier[serviceSize][];
167 for (int i = 0; i < serviceSize; i++) {
169 InstanceIdentifier<?>[] instanceIdentifiers = new InstanceIdentifier[instancesPerService];
170 ret[i] = instanceIdentifiers;
171 for (int id = 0; id < instancesPerService; id++) {
172 instanceIdentifiers[id] = referencableIdentifier(service * instancesPerService + id);
180 private InstanceIdentifier<?> referencableIdentifier(int i) {
181 ReferencableObjectKey key = new ReferencableObjectKey(i);
182 IdentifiableItem<ReferencableObject, ReferencableObjectKey> pathArg = new IdentifiableItem<>(
183 ReferencableObject.class, key);
184 return new InstanceIdentifier<ReferencableObject>(Arrays.<PathArgument> asList(pathArg),
185 ReferencableObject.class);
188 private static class SimpleInputImpl implements SimpleInput {
189 private final InstanceIdentifier<?> identifier;
191 public SimpleInputImpl(InstanceIdentifier<?> _identifier) {
192 this.identifier = _identifier;
196 public <E extends Augmentation<SimpleInput>> E getAugmentation(Class<E> augmentationType) {
201 public InstanceIdentifier<?> getIdentifier() {
202 return this.identifier;
206 public Class<? extends DataObject> getImplementedInterface() {
207 return SimpleInput.class;
211 private static class FooUpdateImpl implements FooUpdate {
213 public Class<? extends DataContainer> getImplementedInterface() {
214 return FooUpdate.class;
218 private static class BarUpdateImpl implements BarUpdate {
220 public Class<? extends DataContainer> getImplementedInterface() {
221 return BarUpdate.class;
225 public InstanceIdentifier<?> getInheritedIdentifier() {
230 private static class FooListenerImpl implements FooListener {
232 List<FooUpdate> receivedFoos = new ArrayList<>();
235 public void onFooUpdate(FooUpdate notification) {
236 receivedFoos.add(notification);
241 private static class CompositeListenerImpl extends FooListenerImpl implements BarListener {
243 List<BarUpdate> receivedBars = new ArrayList<>();
244 List<FlowDelete> receivedDeletes = new ArrayList<>();
247 public void onBarUpdate(BarUpdate notification) {
248 receivedBars.add(notification);
252 public void onFlowDelete(FlowDelete notification) {
253 receivedDeletes.add(notification);