Updated implementation of broker (data services, generated code), added Integration...
[controller.git] / opendaylight / md-sal / sal-binding-broker / src / test / java / org / opendaylight / controller / sal / binding / test / RuntimeCodeGeneratorTest.java
1 package org.opendaylight.controller.sal.binding.test;
2
3 import static org.junit.Assert.*;
4
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.HashMap;
8 import java.util.List;
9 import java.util.Map;
10
11 import javassist.ClassPool;
12
13 import org.junit.Before;
14 import org.junit.Test;
15
16 import static org.opendaylight.controller.sal.binding.codegen.RuntimeCodeHelper.*;
17
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;
42
43 import static org.mockito.Mockito.*;
44
45 public class RuntimeCodeGeneratorTest {
46
47     private RuntimeCodeGenerator codeGenerator;
48     private NotificationInvokerFactory invokerFactory;
49
50     @Before
51     public void initialize() {
52         this.codeGenerator = new RuntimeCodeGenerator(ClassPool.getDefault());
53         this.invokerFactory = codeGenerator.getInvokerFactory();
54     }
55
56     @Test
57     public void testGenerateDirectProxy() {
58         FooService product = codeGenerator.getDirectProxyFor(FooService.class);
59         assertNotNull(product);
60     }
61
62     @Test
63     public void testGenerateRouter() throws Exception {
64         RpcRouter<FooService> product = codeGenerator.getRouterFor(FooService.class);
65         assertNotNull(product);
66         assertNotNull(product.getInvocationProxy());
67
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);
72
73         verifyRouting(product);
74     }
75
76     @Test
77     public void testInvoker() throws Exception {
78
79         FooListenerImpl fooListener = new FooListenerImpl();
80
81         NotificationInvoker invokerFoo = invokerFactory.invokerFor(fooListener);
82
83         
84         assertSame(fooListener,invokerFoo.getDelegate());
85         assertNotNull(invokerFoo.getSupportedNotifications());
86         assertEquals(1, invokerFoo.getSupportedNotifications().size());
87         assertNotNull(invokerFoo.getInvocationProxy());
88
89         FooUpdateImpl fooOne = new FooUpdateImpl();
90         invokerFoo.getInvocationProxy().onNotification(fooOne);
91
92         assertEquals(1, fooListener.receivedFoos.size());
93         assertSame(fooOne, fooListener.receivedFoos.get(0));
94
95         CompositeListenerImpl composite = new CompositeListenerImpl();
96
97         NotificationInvoker invokerComposite = invokerFactory.invokerFor(composite);
98
99         assertNotNull(invokerComposite.getSupportedNotifications());
100         assertEquals(3, invokerComposite.getSupportedNotifications().size());
101         assertNotNull(invokerComposite.getInvocationProxy());
102
103         invokerComposite.getInvocationProxy().onNotification(fooOne);
104
105         assertEquals(1, composite.receivedFoos.size());
106         assertSame(fooOne, composite.receivedFoos.get(0));
107
108         assertEquals(0, composite.receivedBars.size());
109
110         BarUpdateImpl barOne = new BarUpdateImpl();
111
112         invokerComposite.getInvocationProxy().onNotification(barOne);
113
114         assertEquals(1, composite.receivedFoos.size());
115         assertEquals(1, composite.receivedBars.size());
116         assertSame(barOne, composite.receivedBars.get(0));
117
118     }
119
120     private void verifyRouting(RpcRouter<FooService> product) {
121         assertNotNull("Routing table should be initialized", product.getRoutingTable(BaseIdentity.class));
122
123         RpcRoutingTable<BaseIdentity, FooService> routingTable = product.getRoutingTable(BaseIdentity.class);
124
125         int servicesCount = 2;
126         int instancesPerService = 3;
127
128         InstanceIdentifier<?>[][] identifiers = identifiers(servicesCount, instancesPerService);
129         FooService service[] = new FooService[] { mock(FooService.class, "Instance 0"),
130                 mock(FooService.class, "Instance 1") };
131
132         for (int i = 0; i < service.length; i++) {
133             for (InstanceIdentifier<?> instance : identifiers[i]) {
134                 routingTable.updateRoute(instance, service[i]);
135             }
136         }
137
138         assertEquals("All instances should be registered.", servicesCount * instancesPerService, routingTable
139                 .getRoutes().size());
140
141         SimpleInput[] instance_0_input = new SimpleInputImpl[] { new SimpleInputImpl(identifiers[0][0]),
142                 new SimpleInputImpl(identifiers[0][1]), new SimpleInputImpl(identifiers[0][2]) };
143
144         SimpleInput[] instance_1_input = new SimpleInputImpl[] { new SimpleInputImpl(identifiers[1][0]),
145                 new SimpleInputImpl(identifiers[1][1]), new SimpleInputImpl(identifiers[1][2]) };
146
147         // We test sending mock messages
148
149         product.getInvocationProxy().simple(instance_0_input[0]);
150         verify(service[0]).simple(instance_0_input[0]);
151
152         product.getInvocationProxy().simple(instance_0_input[1]);
153         product.getInvocationProxy().simple(instance_0_input[2]);
154
155         verify(service[0]).simple(instance_0_input[1]);
156         verify(service[0]).simple(instance_0_input[2]);
157
158         product.getInvocationProxy().simple(instance_1_input[0]);
159
160         // We should have call to instance 1
161         verify(service[1]).simple(instance_1_input[0]);
162     }
163
164     private InstanceIdentifier<?>[][] identifiers(int serviceSize, int instancesPerService) {
165         InstanceIdentifier<?>[][] ret = new InstanceIdentifier[serviceSize][];
166         int service = 0;
167         for (int i = 0; i < serviceSize; i++) {
168
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);
173             }
174             service++;
175         }
176
177         return ret;
178     }
179
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);
186     }
187
188     private static class SimpleInputImpl implements SimpleInput {
189         private final InstanceIdentifier<?> identifier;
190
191         public SimpleInputImpl(InstanceIdentifier<?> _identifier) {
192             this.identifier = _identifier;
193         }
194
195         @Override
196         public <E extends Augmentation<SimpleInput>> E getAugmentation(Class<E> augmentationType) {
197             return null;
198         }
199
200         @Override
201         public InstanceIdentifier<?> getIdentifier() {
202             return this.identifier;
203         }
204
205         @Override
206         public Class<? extends DataObject> getImplementedInterface() {
207             return SimpleInput.class;
208         }
209     }
210
211     private static class FooUpdateImpl implements FooUpdate {
212         @Override
213         public Class<? extends DataContainer> getImplementedInterface() {
214             return FooUpdate.class;
215         }
216     }
217
218     private static class BarUpdateImpl implements BarUpdate {
219         @Override
220         public Class<? extends DataContainer> getImplementedInterface() {
221             return BarUpdate.class;
222         }
223
224         @Override
225         public InstanceIdentifier<?> getInheritedIdentifier() {
226             return null;
227         }
228     }
229
230     private static class FooListenerImpl implements FooListener {
231
232         List<FooUpdate> receivedFoos = new ArrayList<>();
233
234         @Override
235         public void onFooUpdate(FooUpdate notification) {
236             receivedFoos.add(notification);
237         }
238
239     }
240
241     private static class CompositeListenerImpl extends FooListenerImpl implements BarListener {
242
243         List<BarUpdate> receivedBars = new ArrayList<>();
244         List<FlowDelete> receivedDeletes = new ArrayList<>();
245
246         @Override
247         public void onBarUpdate(BarUpdate notification) {
248             receivedBars.add(notification);
249         }
250
251         @Override
252         public void onFlowDelete(FlowDelete notification) {
253             receivedDeletes.add(notification);
254         }
255
256     }
257 }