2 * Copyright (c) 2014 Cisco Systems, Inc. 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.controller.sal.binding.test;
10 import static org.junit.Assert.*;
12 import java.util.ArrayList;
13 import java.util.Arrays;
14 import java.util.HashMap;
15 import java.util.List;
18 import javassist.ClassPool;
20 import org.junit.Before;
21 import org.junit.Test;
23 import static org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper.*;
25 import org.opendaylight.controller.sal.binding.api.NotificationListener;
26 import org.opendaylight.controller.sal.binding.api.rpc.RpcRouter;
27 import org.opendaylight.controller.sal.binding.api.rpc.RpcRoutingTable;
28 import org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator;
29 import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory;
30 import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory.NotificationInvoker;
31 import org.opendaylight.controller.sal.binding.test.mock.BarListener;
32 import org.opendaylight.controller.sal.binding.test.mock.BarUpdate;
33 import org.opendaylight.controller.sal.binding.test.mock.CompositeListener;
34 import org.opendaylight.controller.sal.binding.test.mock.FlowDelete;
35 import org.opendaylight.controller.sal.binding.test.mock.FooListener;
36 import org.opendaylight.controller.sal.binding.test.mock.FooService;
37 import org.opendaylight.controller.sal.binding.test.mock.FooUpdate;
38 import org.opendaylight.controller.sal.binding.test.mock.InheritedContextInput;
39 import org.opendaylight.controller.sal.binding.test.mock.ReferencableObject;
40 import org.opendaylight.controller.sal.binding.test.mock.ReferencableObjectKey;
41 import org.opendaylight.controller.sal.binding.test.mock.SimpleInput;
42 import org.opendaylight.yangtools.yang.binding.Augmentation;
43 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
44 import org.opendaylight.yangtools.yang.binding.DataContainer;
45 import org.opendaylight.yangtools.yang.binding.DataObject;
46 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
47 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
48 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
50 import static org.mockito.Mockito.*;
52 public class RuntimeCodeGeneratorTest {
54 private RuntimeCodeGenerator codeGenerator;
55 private NotificationInvokerFactory invokerFactory;
58 public void initialize() {
59 this.codeGenerator = new RuntimeCodeGenerator(ClassPool.getDefault());
60 this.invokerFactory = codeGenerator.getInvokerFactory();
64 public void testGenerateDirectProxy() {
65 FooService product = codeGenerator.getDirectProxyFor(FooService.class);
66 assertNotNull(product);
70 public void testGenerateRouter() throws Exception {
71 RpcRouter<FooService> product = codeGenerator.getRouterFor(FooService.class,"test");
72 assertNotNull(product);
73 assertNotNull(product.getInvocationProxy());
75 assertEquals("2 fields should be generated.", 2, product.getInvocationProxy().getClass().getFields().length);
77 verifyRouting(product);
81 public void testInvoker() throws Exception {
83 FooListenerImpl fooListener = new FooListenerImpl();
85 NotificationInvoker invokerFoo = invokerFactory.invokerFor(fooListener);
88 assertSame(fooListener,invokerFoo.getDelegate());
89 assertNotNull(invokerFoo.getSupportedNotifications());
90 assertEquals(1, invokerFoo.getSupportedNotifications().size());
91 assertNotNull(invokerFoo.getInvocationProxy());
93 FooUpdateImpl fooOne = new FooUpdateImpl();
94 invokerFoo.getInvocationProxy().onNotification(fooOne);
96 assertEquals(1, fooListener.receivedFoos.size());
97 assertSame(fooOne, fooListener.receivedFoos.get(0));
99 CompositeListenerImpl composite = new CompositeListenerImpl();
101 NotificationInvoker invokerComposite = invokerFactory.invokerFor(composite);
103 assertNotNull(invokerComposite.getSupportedNotifications());
104 assertEquals(3, invokerComposite.getSupportedNotifications().size());
105 assertNotNull(invokerComposite.getInvocationProxy());
107 invokerComposite.getInvocationProxy().onNotification(fooOne);
109 assertEquals(1, composite.receivedFoos.size());
110 assertSame(fooOne, composite.receivedFoos.get(0));
112 assertEquals(0, composite.receivedBars.size());
114 BarUpdateImpl barOne = new BarUpdateImpl();
116 invokerComposite.getInvocationProxy().onNotification(barOne);
118 assertEquals(1, composite.receivedFoos.size());
119 assertEquals(1, composite.receivedBars.size());
120 assertSame(barOne, composite.receivedBars.get(0));
124 private void verifyRouting(RpcRouter<FooService> product) {
125 assertNotNull("Routing table should be initialized", product.getRoutingTable(BaseIdentity.class));
127 RpcRoutingTable<BaseIdentity, FooService> routingTable = product.getRoutingTable(BaseIdentity.class);
129 int servicesCount = 2;
130 int instancesPerService = 3;
132 InstanceIdentifier<?>[][] identifiers = identifiers(servicesCount, instancesPerService);
133 FooService service[] = new FooService[] { mock(FooService.class, "Instance 0"),
134 mock(FooService.class, "Instance 1") };
136 for (int i = 0; i < service.length; i++) {
137 for (InstanceIdentifier<?> instance : identifiers[i]) {
138 routingTable.updateRoute(instance, service[i]);
142 assertEquals("All instances should be registered.", servicesCount * instancesPerService, routingTable
143 .getRoutes().size());
145 SimpleInput[] instance_0_input = new SimpleInputImpl[] { new SimpleInputImpl(identifiers[0][0]),
146 new SimpleInputImpl(identifiers[0][1]), new SimpleInputImpl(identifiers[0][2]) };
148 SimpleInput[] instance_1_input = new SimpleInputImpl[] { new SimpleInputImpl(identifiers[1][0]),
149 new SimpleInputImpl(identifiers[1][1]), new SimpleInputImpl(identifiers[1][2]) };
151 // We test sending mock messages
153 product.getInvocationProxy().simple(instance_0_input[0]);
154 verify(service[0]).simple(instance_0_input[0]);
156 product.getInvocationProxy().simple(instance_0_input[1]);
157 product.getInvocationProxy().simple(instance_0_input[2]);
159 verify(service[0]).simple(instance_0_input[1]);
160 verify(service[0]).simple(instance_0_input[2]);
162 product.getInvocationProxy().simple(instance_1_input[0]);
164 // We should have call to instance 1
165 verify(service[1]).simple(instance_1_input[0]);
168 private InstanceIdentifier<?>[][] identifiers(int serviceSize, int instancesPerService) {
169 InstanceIdentifier<?>[][] ret = new InstanceIdentifier[serviceSize][];
171 for (int i = 0; i < serviceSize; i++) {
173 InstanceIdentifier<?>[] instanceIdentifiers = new InstanceIdentifier[instancesPerService];
174 ret[i] = instanceIdentifiers;
175 for (int id = 0; id < instancesPerService; id++) {
176 instanceIdentifiers[id] = referencableIdentifier(service * instancesPerService + id);
184 private InstanceIdentifier<?> referencableIdentifier(int i) {
185 ReferencableObjectKey key = new ReferencableObjectKey(i);
186 IdentifiableItem<ReferencableObject, ReferencableObjectKey> pathArg = new IdentifiableItem<>(
187 ReferencableObject.class, key);
188 return new InstanceIdentifier<ReferencableObject>(Arrays.<PathArgument> asList(pathArg),
189 ReferencableObject.class);
192 private static class SimpleInputImpl implements SimpleInput {
193 private final InstanceIdentifier<?> identifier;
195 public SimpleInputImpl(InstanceIdentifier<?> _identifier) {
196 this.identifier = _identifier;
200 public <E extends Augmentation<SimpleInput>> E getAugmentation(Class<E> augmentationType) {
205 public InstanceIdentifier<?> getIdentifier() {
206 return this.identifier;
210 public Class<? extends DataObject> getImplementedInterface() {
211 return SimpleInput.class;
215 private static class FooUpdateImpl implements FooUpdate {
217 public Class<? extends DataContainer> getImplementedInterface() {
218 return FooUpdate.class;
222 private static class BarUpdateImpl implements BarUpdate {
224 public Class<? extends DataContainer> getImplementedInterface() {
225 return BarUpdate.class;
229 public InstanceIdentifier<?> getInheritedIdentifier() {
234 private static class FooListenerImpl implements FooListener {
236 List<FooUpdate> receivedFoos = new ArrayList<>();
239 public void onFooUpdate(FooUpdate notification) {
240 receivedFoos.add(notification);
245 private static class CompositeListenerImpl extends FooListenerImpl implements BarListener {
247 List<BarUpdate> receivedBars = new ArrayList<>();
248 List<FlowDelete> receivedDeletes = new ArrayList<>();
251 public void onBarUpdate(BarUpdate notification) {
252 receivedBars.add(notification);
256 public void onFlowDelete(FlowDelete notification) {
257 receivedDeletes.add(notification);