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