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