Update Robert's coordinates
[honeycomb.git] / infra / translate-utils / src / test / java / io / fd / honeycomb / translate / util / read / cache / DumpCacheManagerTest.java
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package io.fd.honeycomb.translate.util.read.cache;
18
19 import static io.fd.honeycomb.translate.util.read.cache.EntityDumpExecutor.NO_PARAMS;
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertTrue;
22 import static org.mockito.Mockito.when;
23
24 import io.fd.honeycomb.translate.ModificationCache;
25 import io.fd.honeycomb.translate.read.ReadFailedException;
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.Objects;
29 import java.util.Optional;
30 import org.junit.Before;
31 import org.junit.Test;
32 import org.mockito.Mock;
33 import org.mockito.MockitoAnnotations;
34 import org.opendaylight.yangtools.yang.binding.DataObject;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36
37 public class DumpCacheManagerTest {
38
39     @Mock
40     private EntityDumpExecutor<IpDetailsReplyDump, Void> executor;
41     private InstanceIdentifier<DataObj> identifier;
42     private DumpCacheManager<IpDetailsReplyDump, Void> managerPositive;
43     private DumpCacheManager<IpDetailsReplyDump, Void> managerPositiveWithPostProcessing;
44     private DumpCacheManager<IpDetailsReplyDump, Void> managerNegative;
45     private ModificationCache cache;
46     private CacheKeyFactory cacheKeyFactory;
47
48     @Before
49     public void init() {
50         MockitoAnnotations.initMocks(this);
51         managerPositive =
52                 new DumpCacheManager.DumpCacheManagerBuilder<IpDetailsReplyDump, Void>()
53                         .withExecutor(executor)
54                         .acceptOnly(IpDetailsReplyDump.class)
55                         .build();
56
57         managerPositiveWithPostProcessing =
58                 new DumpCacheManager.DumpCacheManagerBuilder<IpDetailsReplyDump, Void>()
59                         .withExecutor(executor)
60                         .acceptOnly(IpDetailsReplyDump.class)
61                         .withPostProcessingFunction(createPostProcessor())
62                         .build();
63
64         managerNegative =
65                 new DumpCacheManager.DumpCacheManagerBuilder<IpDetailsReplyDump, Void>()
66                         .withExecutor(executor)
67                         .acceptOnly(IpDetailsReplyDump.class)
68                         .build();
69
70         cache = new ModificationCache();
71         identifier = InstanceIdentifier.create(DataObj.class);
72         //manager uses this implementation by default, so it can be used to test behaviour
73         cacheKeyFactory = new TypeAwareIdentifierCacheKeyFactory(IpDetailsReplyDump.class);
74
75     }
76
77     /**
78      * This test verify full dump-caching cycle
79      */
80     @Test
81     public void testCaching() throws ReadFailedException {
82         final IpDetailsReplyDump stage1Data = new IpDetailsReplyDump();
83         final String key = cacheKeyFactory.createKey(identifier, NO_PARAMS);
84
85
86         // executor cant return null data
87         when(executor.executeDump(identifier, NO_PARAMS)).thenReturn(new IpDetailsReplyDump());
88
89         final Optional<IpDetailsReplyDump> stage1Optional = managerNegative.getDump(identifier, cache);
90
91         // this is first call so instance should be from executor
92         // and it should be cached after calling executor
93         assertEquals(true, stage1Optional.isPresent());
94         assertEquals(stage1Data, stage1Optional.get());
95         assertEquals(true, cache.containsKey(key));
96         assertEquals(stage1Data, cache.get(key));
97
98         //rebind executor with other data
99         IpDetailsReplyDump stage2LoadedDump = new IpDetailsReplyDump();
100         when(executor.executeDump(identifier, NO_PARAMS)).thenReturn(stage2LoadedDump);
101
102         final Optional<IpDetailsReplyDump> stage2Optional = managerPositive.getDump(identifier, cache);
103
104         assertEquals(true, stage2Optional.isPresent());
105         assertEquals(stage2LoadedDump, stage2Optional.get());
106
107         //rebind executor with other data
108         IpDetailsReplyDump stage3LoadedDump = new IpDetailsReplyDump();
109         when(executor.executeDump(identifier, NO_PARAMS)).thenReturn(stage3LoadedDump);
110
111         final Optional<IpDetailsReplyDump> stage3Optional = managerPositive.getDump(identifier, cache);
112         assertEquals(true, stage3Optional.isPresent());
113         //check if it returns instance cached from previous stage
114         assertEquals(stage2LoadedDump, stage3Optional.get());
115     }
116
117     @Test
118     public void testPostprocessing() throws ReadFailedException {
119         IpDetailsReplyDump dump = new IpDetailsReplyDump();
120         IpDetails details = new IpDetails();
121         details.swIfIndex = 2;
122         dump.ipDetails.add(details);
123
124         when(executor.executeDump(identifier, null)).thenReturn(dump);
125
126         Optional<IpDetailsReplyDump> optionalDump =
127                 managerPositiveWithPostProcessing.getDump(identifier, cache);
128
129         assertEquals(true, optionalDump.isPresent());
130         assertEquals(1, optionalDump.get().ipDetails.size());
131         assertEquals(7, optionalDump.get().ipDetails.get(0).swIfIndex);
132     }
133
134     @Test
135     public void testSameKeyDifferentTypes() throws ReadFailedException {
136         final DumpCacheManager<String, Void> stringManager =
137             new DumpCacheManager.DumpCacheManagerBuilder<String, Void>()
138                 .withExecutor((InstanceIdentifier, Void) -> "value")
139                 .acceptOnly(String.class)
140                 .build();
141
142         final DumpCacheManager<Integer, Void> intManager = new DumpCacheManager.DumpCacheManagerBuilder<Integer, Void>()
143             .acceptOnly(Integer.class)
144             .withExecutor((InstanceIdentifier, Void) -> 3).build();
145
146         final Optional<String> stringDump = stringManager.getDump(identifier, cache);
147         final Optional<Integer> integerDump = intManager.getDump(identifier, cache);
148
149         assertTrue(stringDump.isPresent());
150         assertTrue(integerDump.isPresent());
151         assertEquals("value", stringDump.get());
152         assertEquals(3, integerDump.get().intValue());
153
154     }
155
156     @Test
157     public void testCachingWithDifferentParams() throws ReadFailedException {
158         final DumpCacheManager<Integer, Integer> manager =
159             new DumpCacheManager.DumpCacheManagerBuilder<Integer, Integer>()
160                 .withExecutor((iid, param) -> param)
161                 .acceptOnly(Integer.class)
162                 .build();
163
164         final Optional<Integer> dump1 = manager.getDump(identifier, cache, 1);
165         final Optional<Integer> dump2 = manager.getDump(identifier, cache, 2);
166
167         assertEquals(1, dump1.get().intValue());
168         assertEquals(2, dump2.get().intValue());
169     }
170
171     private EntityDumpPostProcessingFunction<IpDetailsReplyDump> createPostProcessor() {
172         return ipDetailsReplyDump -> {
173             IpDetailsReplyDump modified = new IpDetailsReplyDump();
174
175             for (IpDetails detail : ipDetailsReplyDump.ipDetails) {
176                 IpDetails modifiedDetail = new IpDetails();
177                 modifiedDetail.swIfIndex = detail.swIfIndex + 5;
178
179                 modified.ipDetails.add(modifiedDetail);
180             }
181
182             return modified;
183         };
184     }
185
186     private interface DataObj extends DataObject {
187     }
188
189     private static final class IpDetailsReplyDump {
190         List<IpDetails> ipDetails = new ArrayList<>();
191
192         @Override
193         public boolean equals(final Object o) {
194             if (this == o) {
195                 return true;
196             }
197             if (o == null || getClass() != o.getClass()) {
198                 return false;
199             }
200             final IpDetailsReplyDump that = (IpDetailsReplyDump) o;
201             return Objects.equals(ipDetails, that.ipDetails);
202         }
203
204         @Override
205         public int hashCode() {
206             return Objects.hash(ipDetails);
207         }
208     }
209
210     private static final class IpDetails {
211         int swIfIndex;
212     }
213 }