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