3dd4d6ddab6397364aeb3dea5a9e2ee29f8ae87e
[genius.git] / idmanager / idmanager-impl / src / test / java / org / opendaylight / genius / idmanager / test / IdManagerTest.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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.genius.idmanager.test;
9
10 import static java.util.Comparator.comparing;
11 import static java.util.concurrent.TimeUnit.SECONDS;
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertFalse;
14 import static org.junit.Assert.assertNotNull;
15 import static org.junit.Assert.assertTrue;
16 import static org.junit.Assert.fail;
17
18 import com.google.common.collect.Sets;
19 import java.util.ArrayList;
20 import java.util.Arrays;
21 import java.util.Collections;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Optional;
25 import java.util.Set;
26 import java.util.concurrent.CountDownLatch;
27 import java.util.concurrent.ExecutionException;
28 import java.util.concurrent.ExecutorService;
29 import java.util.concurrent.Future;
30 import java.util.concurrent.atomic.AtomicReference;
31 import java.util.stream.Collectors;
32 import javax.inject.Inject;
33 import junit.framework.AssertionFailedError;
34 import org.eclipse.jdt.annotation.NonNull;
35 import org.eclipse.jdt.annotation.Nullable;
36 import org.junit.Before;
37 import org.junit.ComparisonFailure;
38 import org.junit.Ignore;
39 import org.junit.Rule;
40 import org.junit.Test;
41 import org.junit.rules.MethodRule;
42 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
43 import org.opendaylight.genius.datastoreutils.testutils.AsyncEventsWaiter;
44 import org.opendaylight.genius.datastoreutils.testutils.JobCoordinatorEventsWaiter;
45 import org.opendaylight.genius.datastoreutils.testutils.JobCoordinatorTestModule;
46 import org.opendaylight.genius.datastoreutils.testutils.TestableDataTreeChangeListenerModule;
47 import org.opendaylight.genius.idmanager.IdUtils;
48 import org.opendaylight.infrautils.inject.guice.testutils.GuiceRule;
49 import org.opendaylight.infrautils.testutils.LogCaptureRule;
50 import org.opendaylight.infrautils.testutils.LogRule;
51 import org.opendaylight.infrautils.utils.concurrent.Executors;
52 import org.opendaylight.mdsal.binding.api.DataBroker;
53 import org.opendaylight.mdsal.binding.api.WriteTransaction;
54 import org.opendaylight.mdsal.binding.testutils.AssertDataObjects;
55 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
56 import org.opendaylight.mdsal.common.api.ReadFailedException;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInput;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInputBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdPools;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdOutput;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.IdPool;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.IdPoolBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.IdPoolKey;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.id.pool.AvailableIdsHolder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.id.pool.AvailableIdsHolderBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.id.pool.ChildPools;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.id.pool.ChildPoolsBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.id.pool.ChildPoolsKey;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.id.pool.IdEntries;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.id.pool.IdEntriesKey;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.id.pool.ReleasedIdsHolder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.id.pool.ReleasedIdsHolderBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.released.ids.DelayedIdEntries;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.released.ids.DelayedIdEntriesBuilder;
83 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
84 import org.opendaylight.yangtools.yang.common.RpcError;
85 import org.opendaylight.yangtools.yang.common.RpcResult;
86 import org.slf4j.Logger;
87 import org.slf4j.LoggerFactory;
88
89
90 public class IdManagerTest {
91
92     private static final Logger LOG = LoggerFactory.getLogger(IdManagerTest.class);
93
94     private static final String TEST_KEY1 = "test-key1";
95     private static final String TEST_KEY2 = "test-key2";
96     private static final String ID_POOL_NAME = "test-pool";
97     private static final int BLOCK_SIZE = 10;
98     private static final long ID_LOW = 0L;
99     private static final long ID_HIGH = 100L;
100
101     // public static @ClassRule RunUntilFailureClassRule classRepeater = new RunUntilFailureClassRule();
102     // public @Rule RunUntilFailureRule repeater = new RunUntilFailureRule(classRepeater);
103
104     public @Rule LogRule logRule = new LogRule();
105     public @Rule LogCaptureRule logCaptureRule = new LogCaptureRule();
106
107     public @Rule MethodRule guice = new GuiceRule(IdManagerTestModule.class,
108             TestableDataTreeChangeListenerModule.class, JobCoordinatorTestModule.class);
109
110     private @Inject IdManagerService idManagerService;
111     private @Inject DataBroker dataBroker;
112     private @Inject AsyncEventsWaiter asyncEventsWaiter;
113     private @Inject JobCoordinatorEventsWaiter coordinatorEventsWaiter;
114     private @Inject IdUtils idUtils;
115
116     private SingleTransactionDataBroker singleTxdataBroker;
117
118     @Before
119     public void before() {
120         singleTxdataBroker = new SingleTransactionDataBroker(dataBroker);
121     }
122
123     @Test
124     public void testCreateIdPool() throws Exception {
125         CreateIdPoolInput createIdPoolInput = new CreateIdPoolInputBuilder().setHigh(ID_HIGH).setLow(ID_LOW)
126                 .setPoolName(ID_POOL_NAME).build();
127         assertTrue(idManagerService.createIdPool(createIdPoolInput).get().isSuccessful());
128         coordinatorEventsWaiter.awaitEventsConsumption();
129         validateIdPools(ExpectedCreateIdPoolObjects.idPoolCreateParent(),
130                 ExpectedCreateIdPoolObjects.idPoolCreateChild());
131     }
132
133     @Test
134     public void testAllocateId() throws Exception {
135         CreateIdPoolInput createIdPoolInput = new CreateIdPoolInputBuilder().setHigh(ID_HIGH).setLow(ID_LOW)
136                 .setPoolName(ID_POOL_NAME).build();
137         AllocateIdInput allocateIdInput = new AllocateIdInputBuilder().setIdKey(TEST_KEY1).setPoolName(ID_POOL_NAME)
138                 .build();
139         idManagerService.createIdPool(createIdPoolInput);
140         assertEquals(idManagerService.allocateId(allocateIdInput).get().getResult().getIdValue().longValue(), 0L);
141         coordinatorEventsWaiter.awaitEventsConsumption();
142
143         validateIdPools(ExpectedAllocateIdObjects.idPoolParent(), ExpectedAllocateIdObjects.idPoolChild());
144     }
145
146     @Test
147     public void testReleaseId() throws Exception {
148         CreateIdPoolInput createIdPoolInput = new CreateIdPoolInputBuilder().setHigh(ID_HIGH).setLow(ID_LOW)
149                 .setPoolName(ID_POOL_NAME).build();
150         AllocateIdInput allocateIdInput = new AllocateIdInputBuilder().setIdKey(TEST_KEY1).setPoolName(ID_POOL_NAME)
151                 .build();
152         ReleaseIdInput releaseIdInput = new ReleaseIdInputBuilder().setIdKey(TEST_KEY1).setPoolName(ID_POOL_NAME)
153                 .build();
154         idManagerService.createIdPool(createIdPoolInput);
155         Future<RpcResult<AllocateIdOutput>> allocateIdResult = idManagerService.allocateId(allocateIdInput);
156         assertTrue(allocateIdResult.get().isSuccessful());
157         Future<RpcResult<ReleaseIdOutput>> result = idManagerService.releaseId(releaseIdInput);
158         assertTrue(result.get().isSuccessful());
159         assertEquals(allocateIdResult.get().getResult().getIdValue(), result.get().getResult().getIdValues().get(0));
160         coordinatorEventsWaiter.awaitEventsConsumption();
161
162         validateIdPools(ExpectedReleaseIdObjects.idPoolParent(), ExpectedReleaseIdObjects.idPoolChild());
163     }
164
165     @Test
166     public void testAllocateIdBlockFromReleasedIds() throws Exception {
167         CreateIdPoolInput createIdPoolInput = new CreateIdPoolInputBuilder().setHigh(ID_HIGH).setLow(ID_LOW)
168                 .setPoolName(ID_POOL_NAME).build();
169         AllocateIdInput allocateIdInput = new AllocateIdInputBuilder().setIdKey(TEST_KEY2).setPoolName(ID_POOL_NAME)
170                 .build();
171         idManagerService.createIdPool(createIdPoolInput);
172         idManagerService.allocateId(allocateIdInput);
173         coordinatorEventsWaiter.awaitEventsConsumption();
174         asyncEventsWaiter.awaitEventsConsumption();
175
176         String localPoolName = idUtils.getLocalPoolName(ID_POOL_NAME);
177         IdPool parentIdPool = new IdPoolBuilder().setPoolName(ID_POOL_NAME).withKey(new IdPoolKey(ID_POOL_NAME))
178                 .setAvailableIdsHolder(createAvailableIdHolder(ID_LOW, ID_HIGH, ID_HIGH + 1))
179                 .setReleasedIdsHolder(createReleaseIdHolder(Collections.emptyList())).build();
180         IdPool childPool = new IdPoolBuilder().setPoolName(localPoolName).withKey(new IdPoolKey(localPoolName))
181                 .setReleasedIdsHolder(createReleaseIdHolder(Arrays.asList(1L, 2L, 3L)))
182                 .setAvailableIdsHolder(createAvailableIdHolder(0L, 9L, 10L)).build();
183         WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
184         tx.merge(LogicalDatastoreType.CONFIGURATION, getIdPoolIdentifier(ID_POOL_NAME), parentIdPool);
185         tx.merge(LogicalDatastoreType.CONFIGURATION, getIdPoolIdentifier(localPoolName), childPool);
186         tx.commit().get();
187
188         AllocateIdInput allocateIdInput2 = new AllocateIdInputBuilder().setIdKey(TEST_KEY1).setPoolName(ID_POOL_NAME)
189                 .build();
190         assertEquals(idManagerService.allocateId(allocateIdInput2).get().getResult().getIdValue().longValue(), 1L);
191
192         coordinatorEventsWaiter.awaitEventsConsumption();
193         validateIdPools(ExpectedAllocateIdFromReleasedId.idPoolParent(),
194                 ExpectedAllocateIdFromReleasedId.idPoolChild());
195     }
196
197     @Test
198     public void testDeletePool() throws Exception {
199         CreateIdPoolInput createIdPoolInput = new CreateIdPoolInputBuilder().setHigh(ID_HIGH).setLow(ID_LOW)
200                 .setPoolName(ID_POOL_NAME).build();
201         idManagerService.createIdPool(createIdPoolInput);
202         DeleteIdPoolInput deleteIdPoolInput = new DeleteIdPoolInputBuilder().setPoolName(ID_POOL_NAME).build();
203         assertTrue(idManagerService.deleteIdPool(deleteIdPoolInput).get().isSuccessful());
204         coordinatorEventsWaiter.awaitEventsConsumption();
205         Optional<IdPool> actualIdPoolParent = singleTxdataBroker.syncReadOptional(LogicalDatastoreType.CONFIGURATION,
206                 InstanceIdentifier.builder(IdPools.class).child(IdPool.class, new IdPoolKey(ID_POOL_NAME)).build());
207         Optional<IdPool> actualIdPoolChild = singleTxdataBroker.syncReadOptional(LogicalDatastoreType.CONFIGURATION,
208                 InstanceIdentifier.builder(IdPools.class)
209                         .child(IdPool.class, new IdPoolKey(idUtils.getLocalPoolName(ID_POOL_NAME))).build());
210         assertFalse(actualIdPoolParent.isPresent());
211         assertFalse(actualIdPoolChild.isPresent());
212     }
213
214     @Test
215     @SuppressWarnings("checkstyle:IllegalThrows") // OK as exceptionInExecutor can't be Exception & AssertionFailedError
216     public void testMultithreadedIdAllocationFromAvailableIds() throws Throwable {
217         CreateIdPoolInput createIdPoolInput = new CreateIdPoolInputBuilder().setHigh(ID_HIGH).setLow(ID_LOW)
218                 .setPoolName(ID_POOL_NAME).build();
219         idManagerService.createIdPool(createIdPoolInput);
220         requestIdsConcurrently(false);
221         coordinatorEventsWaiter.awaitEventsConsumption();
222         IdPool actualIdPoolChild = getUpdatedActualChildPool();
223         IdPool actualIdPoolParent = getUpdatedActualParentPool();
224         // Cannot compare the idEntries since we cannot guarantee which idKey gets what value.
225         // However the allocated id values uniqueness is verified in requestIdsConcurrently method.
226         AssertDataObjects.assertEqualBeans(
227                 ExpectedAllocateIdMultipleRequestsFromAvailableIds.idPoolParent().getAvailableIdsHolder(),
228                 actualIdPoolParent.getAvailableIdsHolder());
229         AssertDataObjects.assertEqualBeans(ExpectedAllocateIdMultipleRequestsFromAvailableIds.idPoolChild(),
230                 actualIdPoolChild);
231     }
232
233     @Test
234     @Ignore
235     @SuppressWarnings("checkstyle:IllegalThrows") // OK as exceptionInExecutor can't be Exception & AssertionFailedError
236     public void testMultithreadedIdAllocationFromReleaseIds() throws Throwable {
237         CreateIdPoolInput createIdPoolInput = new CreateIdPoolInputBuilder().setHigh(ID_HIGH).setLow(ID_LOW)
238                 .setPoolName(ID_POOL_NAME).build();
239         AllocateIdInput allocateIdInput = new AllocateIdInputBuilder().setIdKey(TEST_KEY1).setPoolName(ID_POOL_NAME)
240                 .build();
241         idManagerService.createIdPool(createIdPoolInput);
242         idManagerService.allocateId(allocateIdInput);
243         // Should wait for all job to complete.
244         coordinatorEventsWaiter.awaitEventsConsumption();
245
246         String localPoolName = idUtils.getLocalPoolName(ID_POOL_NAME);
247         IdPool parentIdPool = new IdPoolBuilder().setPoolName(ID_POOL_NAME).withKey(new IdPoolKey(ID_POOL_NAME))
248                 .setReleasedIdsHolder(createReleaseIdHolder(Collections.emptyList())).build();
249         IdPool childPool = new IdPoolBuilder().setPoolName(localPoolName).withKey(new IdPoolKey(localPoolName))
250                 .setReleasedIdsHolder(createReleaseIdHolder(Arrays.asList(1L, 2L, 3L)))
251                 .setAvailableIdsHolder(createAvailableIdHolder(0L, 9L, 10L)).build();
252         WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
253         tx.merge(LogicalDatastoreType.CONFIGURATION, getIdPoolIdentifier(ID_POOL_NAME), parentIdPool);
254         tx.merge(LogicalDatastoreType.CONFIGURATION, getIdPoolIdentifier(localPoolName), childPool);
255         tx.commit().get();
256         // Wait for the changes to be available on the caches.
257         asyncEventsWaiter.awaitEventsConsumption();
258         requestIdsConcurrently(false);
259         coordinatorEventsWaiter.awaitEventsConsumption();
260         asyncEventsWaiter.awaitEventsConsumption();
261
262         IdPool actualIdPoolChild = getUpdatedActualChildPool();
263         IdPool actualIdPoolParent = getUpdatedActualParentPool();
264         // Cannot compare the idEntries since we cannot guarantee which idKey gets what value.
265         // However the allocated id values uniqueness is verified in requestIdsConcurrently method.
266         AssertDataObjects.assertEqualBeans(
267                 ExpectedAllocateIdMultipleRequestsFromReleaseIds.idPoolParent().getReleasedIdsHolder(),
268                 actualIdPoolParent.getReleasedIdsHolder());
269         AssertDataObjects.assertEqualBeans(ExpectedAllocateIdMultipleRequestsFromReleaseIds.idPoolChild(),
270                 actualIdPoolChild);
271     }
272
273     @Test
274     @SuppressWarnings("checkstyle:IllegalThrows") // OK as exceptionInExecutor can't be Exception & AssertionFailedError
275     public void testMultithreadedIdAllocationForSameKeyFromAvailableIds() throws Throwable {
276         CreateIdPoolInput createIdPoolInput = new CreateIdPoolInputBuilder().setHigh(ID_HIGH).setLow(ID_LOW)
277                 .setPoolName(ID_POOL_NAME).build();
278         idManagerService.createIdPool(createIdPoolInput);
279         requestIdsConcurrently(true);
280         coordinatorEventsWaiter.awaitEventsConsumption();
281
282         validateIdPools(ExpectedAllocateIdObjects.idPoolParent(), ExpectedAllocateIdObjects.idPoolChild());
283     }
284
285     @Test
286     @SuppressWarnings("checkstyle:IllegalThrows") // OK as exceptionInExecutor can't be Exception & AssertionFailedError
287     public void testMultithreadedIdAllocationForSameKeyFromReleasedIds() throws Throwable {
288         CreateIdPoolInput createIdPoolInput = new CreateIdPoolInputBuilder().setHigh(ID_HIGH).setLow(ID_LOW)
289                 .setPoolName(ID_POOL_NAME).build();
290         AllocateIdInput allocateIdInput = new AllocateIdInputBuilder().setIdKey(TEST_KEY2).setPoolName(ID_POOL_NAME)
291                 .build();
292         idManagerService.createIdPool(createIdPoolInput);
293         idManagerService.allocateId(allocateIdInput);
294         coordinatorEventsWaiter.awaitEventsConsumption();
295         asyncEventsWaiter.awaitEventsConsumption();
296
297         String localPoolName = idUtils.getLocalPoolName(ID_POOL_NAME);
298         IdPool parentIdPool = new IdPoolBuilder().setPoolName(ID_POOL_NAME).withKey(new IdPoolKey(ID_POOL_NAME))
299                 .setAvailableIdsHolder(createAvailableIdHolder(ID_LOW, ID_HIGH, ID_HIGH + 1))
300                 .setReleasedIdsHolder(createReleaseIdHolder(Collections.emptyList())).build();
301         IdPool childPool = new IdPoolBuilder().setPoolName(localPoolName).withKey(new IdPoolKey(localPoolName))
302                 .setReleasedIdsHolder(createReleaseIdHolder(Arrays.asList(1L, 2L, 3L)))
303                 .setAvailableIdsHolder(createAvailableIdHolder(0L, 9L, 10L)).build();
304         WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
305         tx.merge(LogicalDatastoreType.CONFIGURATION, getIdPoolIdentifier(ID_POOL_NAME), parentIdPool);
306         tx.merge(LogicalDatastoreType.CONFIGURATION, getIdPoolIdentifier(localPoolName), childPool);
307         tx.commit().get();
308         requestIdsConcurrently(true);
309         coordinatorEventsWaiter.awaitEventsConsumption();
310         validateIdPools(ExpectedAllocateIdFromReleasedId.idPoolParent(),
311                 ExpectedAllocateIdFromReleasedId.idPoolChild());
312     }
313
314     @SuppressWarnings("checkstyle:IllegalThrows") // OK as exceptionInExecutor can't be Exception & AssertionFailedError
315     private void requestIdsConcurrently(boolean isSameKey) throws Throwable {
316         int numberOfTasks = 3;
317         CountDownLatch latch = new CountDownLatch(numberOfTasks);
318         Set<Long> idSet = Sets.newConcurrentHashSet();
319         ExecutorService executor = Executors.newCachedThreadPool("requestIdsConcurrently()", LOG);
320         AtomicReference<Throwable> exceptionInExecutorAtomic = new AtomicReference<>();
321         for (int i = 0; i < numberOfTasks; i++) {
322             final String idKey;
323             if (isSameKey) {
324                 idKey = TEST_KEY1;
325             } else {
326                 idKey = TEST_KEY1 + i;
327             }
328             executor.execute(() -> {
329                 // Any exception thrown inside this background thread will not cause the test to fail
330                 // so you cannot use assert* here but must set the exceptionInExecutor which is checked after
331                 Future<RpcResult<AllocateIdOutput>> result;
332                 result = idManagerService.allocateId(
333                         new AllocateIdInputBuilder().setPoolName(ID_POOL_NAME).setIdKey(idKey).build());
334                 try {
335                     if (result.get().isSuccessful()) {
336                         Long idValue = result.get().getResult().getIdValue().toJava();
337                         idSet.add(idValue);
338                         if (idValue > ID_LOW + BLOCK_SIZE) {
339                             exceptionInExecutorAtomic.set(new AssertionFailedError("idValue <= ID_LOW + BLOCK_SIZE"));
340                         }
341                     } else {
342                         RpcError error = result.get().getErrors().iterator().next();
343                         if (!error.getCause().getMessage().contains("Ids exhausted for pool : " + ID_POOL_NAME)) {
344                             exceptionInExecutorAtomic.set(error.getCause());
345                         }
346                     }
347                 } catch (InterruptedException | ExecutionException e) {
348                     exceptionInExecutorAtomic.set(e);
349                 } finally {
350                     latch.countDown();
351                 }
352             });
353         }
354         if (!latch.await(13, SECONDS)) {
355             fail("latch.await(13, SECONDS) timed out :(");
356         }
357         Throwable exceptionInExecutor = exceptionInExecutorAtomic.get();
358         if (exceptionInExecutor != null) {
359             throw exceptionInExecutor;
360         }
361         if (isSameKey) {
362             assertEquals(1, idSet.size());
363         } else {
364             assertEquals(numberOfTasks, idSet.size());
365         }
366     }
367
368     private static InstanceIdentifier<IdPool> getIdPoolIdentifier(String poolName) {
369         InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idBuilder =
370                 InstanceIdentifier.builder(IdPools.class).child(IdPool.class, new IdPoolKey(poolName));
371         return idBuilder.build();
372     }
373
374     private static ReleasedIdsHolder createReleaseIdHolder(List<Long> delayedIds) {
375         List<DelayedIdEntries> delayedIdEntries = new ArrayList<>();
376         for (Long id : delayedIds) {
377             delayedIdEntries.add(new DelayedIdEntriesBuilder().setId(id).setReadyTimeSec(0L).build());
378         }
379         return new ReleasedIdsHolderBuilder().setDelayedIdEntries(delayedIdEntries)
380                 .setAvailableIdCount((long) delayedIds.size()).build();
381     }
382
383     private static AvailableIdsHolder createAvailableIdHolder(long start, long end, long cursor) {
384         return new AvailableIdsHolderBuilder().setStart(start).setEnd(end).setCursor(cursor).build();
385     }
386
387     private void validateIdPools(IdPool expectedIdPoolParent, IdPool expectedIdPoolChild)
388             throws ReadFailedException, ComparisonFailure {
389         IdPool actualIdPoolParent = getUpdatedActualParentPool();
390         IdPool actualIdPoolChild = getUpdatedActualChildPool();
391
392         assertNotNull(actualIdPoolParent);
393         assertNotNull(actualIdPoolChild);
394         AssertDataObjects.assertEqualBeans(expectedIdPoolParent, actualIdPoolParent);
395         AssertDataObjects.assertEqualBeans(expectedIdPoolChild, actualIdPoolChild);
396
397     }
398
399     private IdPool getUpdatedActualChildPool() throws ReadFailedException {
400         String localPoolName = idUtils.getLocalPoolName(ID_POOL_NAME);
401         IdPool idPoolChildFromDS = singleTxdataBroker.syncRead(LogicalDatastoreType.CONFIGURATION,
402                 InstanceIdentifier.builder(IdPools.class).child(IdPool.class, new IdPoolKey(localPoolName)).build());
403         List<DelayedIdEntries> actualDelayedIdEntries = idPoolChildFromDS.getReleasedIdsHolder().getDelayedIdEntries();
404         IdPool actualIdPoolChild = idPoolChildFromDS;
405         if (actualDelayedIdEntries != null) {
406             List<DelayedIdEntries> updatedDelayedIdEntries = actualDelayedIdEntries.stream()
407                     .map(delayedIdEntry -> new DelayedIdEntriesBuilder().setId(delayedIdEntry.getId())
408                             .setReadyTimeSec(0L).build())
409                     .collect(Collectors.toList());
410             ReleasedIdsHolder releasedId = new ReleasedIdsHolderBuilder(idPoolChildFromDS.getReleasedIdsHolder())
411                     .setDelayedIdEntries(updatedDelayedIdEntries).build();
412             actualIdPoolChild = new IdPoolBuilder(idPoolChildFromDS).setReleasedIdsHolder(releasedId).build();
413         }
414         return actualIdPoolChild;
415     }
416
417     private IdPool getUpdatedActualParentPool() throws ReadFailedException {
418         IdPool idPoolParentFromDS = singleTxdataBroker.syncRead(LogicalDatastoreType.CONFIGURATION,
419                 InstanceIdentifier.builder(IdPools.class).child(IdPool.class, new IdPoolKey(ID_POOL_NAME)).build());
420         @NonNull Map<ChildPoolsKey, ChildPools> childPool = idPoolParentFromDS.nonnullChildPools();
421
422         List<ChildPools> childPoolList = childPool.values().stream().collect(Collectors.toList());
423         List<ChildPools> updatedChildPool = childPoolList.stream()
424                 .map(child -> new ChildPoolsBuilder(child).setLastAccessTime(0L).build()).collect(Collectors.toList());
425
426         @Nullable Map<IdEntriesKey, IdEntries> idEntries =  idPoolParentFromDS.getIdEntries();
427         IdPoolBuilder idPoolBuilder = new IdPoolBuilder(idPoolParentFromDS);
428         if (idEntries != null) {
429             List<IdEntries> sortedIdEntries = idEntries.values().stream().sorted(comparing(IdEntries::getIdKey))
430                     .collect(Collectors.toList());
431             idPoolBuilder.setIdEntries(sortedIdEntries);
432         }
433         return idPoolBuilder.setChildPools(updatedChildPool).build();
434     }
435 }