98d79bee8bffaf40adacec43c95a665c5300b495
[controller.git] / opendaylight / md-sal / sal-inmemory-datastore / src / test / java / org / opendaylight / controller / md / sal / dom / store / impl / DatastoreTestTask.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.md.sal.dom.store.impl;
9
10 import static org.junit.Assert.assertTrue;
11 import static org.junit.Assert.fail;
12
13 import java.util.concurrent.ExecutionException;
14 import java.util.concurrent.TimeUnit;
15 import java.util.concurrent.TimeoutException;
16
17 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
18 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
19 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
20 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
21 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
22 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
23 import org.opendaylight.controller.sal.core.spi.data.DOMStoreThreePhaseCommitCohort;
24 import org.opendaylight.yangtools.concepts.ListenerRegistration;
25 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
26 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
27
28 import com.google.common.base.Preconditions;
29 import com.google.common.util.concurrent.SettableFuture;
30
31 public class DatastoreTestTask {
32
33     private final DOMStore store;
34     private AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> changeListener;
35
36     private WriteTransactionCustomizer setup;
37     private WriteTransactionCustomizer write;
38     private ReadTransactionVerifier read;
39     private WriteTransactionCustomizer cleanup;
40     private YangInstanceIdentifier changePath;
41     private DataChangeScope changeScope;
42     private volatile boolean postSetup = false;
43     private final ChangeEventListener internalListener;
44     private final TestDCLExecutorService dclExecutorService;
45
46     public DatastoreTestTask(final DOMStore datastore, final TestDCLExecutorService dclExecutorService) {
47         this.store = datastore;
48         this.dclExecutorService = dclExecutorService;
49         internalListener = new ChangeEventListener();
50     }
51
52     public DatastoreTestTask changeListener(final YangInstanceIdentifier path, final DataChangeScope scope,
53             final AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> changeListener) {
54         this.changeListener = changeListener;
55         this.changePath = path;
56         this.changeScope = scope;
57         return this;
58     }
59
60     public DatastoreTestTask changeListener(final YangInstanceIdentifier path, final DataChangeScope scope) {
61         this.changePath = path;
62         this.changeScope = scope;
63         return this;
64     }
65
66     public DatastoreTestTask setup(final WriteTransactionCustomizer setup) {
67         this.setup = setup;
68         return this;
69     }
70
71     public DatastoreTestTask test(final WriteTransactionCustomizer write) {
72         this.write = write;
73         return this;
74     }
75
76     public DatastoreTestTask read(final ReadTransactionVerifier read) {
77         this.read = read;
78         return this;
79     }
80
81     public DatastoreTestTask cleanup(final WriteTransactionCustomizer cleanup) {
82         this.cleanup = cleanup;
83         return this;
84     }
85
86     public void run() throws InterruptedException, ExecutionException, TimeoutException {
87         if (setup != null) {
88             execute(setup);
89         }
90         ListenerRegistration<ChangeEventListener> registration = null;
91         if (changePath != null) {
92             registration = store.registerChangeListener(changePath, internalListener, changeScope);
93         }
94
95         Preconditions.checkState(write != null, "Write Transaction must be set.");
96
97         postSetup = true;
98         dclExecutorService.afterTestSetup();
99
100         execute(write);
101         if (registration != null) {
102             registration.close();
103         }
104
105         if (changeListener != null) {
106             changeListener.onDataChanged(getChangeEvent());
107         }
108         if (read != null) {
109             read.verify(store.newReadOnlyTransaction());
110         }
111         if (cleanup != null) {
112             execute(cleanup);
113         }
114     }
115
116     public AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> getChangeEvent() {
117         try {
118             return internalListener.receivedChange.get(10, TimeUnit.SECONDS);
119         } catch( Exception e ) {
120             fail( "Error getting the AsyncDataChangeEvent from the Future: " + e );
121         }
122
123         // won't get here
124         return null;
125     }
126
127     public void verifyNoChangeEvent() {
128         try {
129             Object unexpected = internalListener.receivedChange.get(500, TimeUnit.MILLISECONDS);
130             fail( "Got unexpected AsyncDataChangeEvent from the Future: " + unexpected );
131         } catch( TimeoutException e ) {
132             // Expected
133         } catch( Exception e ) {
134             fail( "Error getting the AsyncDataChangeEvent from the Future: " + e );
135         }
136     }
137
138     private void execute(final WriteTransactionCustomizer writeCustomizer) throws InterruptedException,
139             ExecutionException {
140         DOMStoreReadWriteTransaction tx = store.newReadWriteTransaction();
141         writeCustomizer.customize(tx);
142         DOMStoreThreePhaseCommitCohort cohort = tx.ready();
143         assertTrue(cohort.canCommit().get());
144         cohort.preCommit().get();
145         cohort.commit().get();
146     }
147
148     public interface WriteTransactionCustomizer {
149         public void customize(DOMStoreReadWriteTransaction tx);
150     }
151
152     public interface ReadTransactionVerifier {
153         public void verify(DOMStoreReadTransaction tx);
154     }
155
156     private final class ChangeEventListener implements
157             AsyncDataChangeListener<YangInstanceIdentifier, NormalizedNode<?, ?>> {
158
159         protected final SettableFuture<AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>>> receivedChange = SettableFuture
160                 .create();
161
162         @Override
163         public void onDataChanged(final AsyncDataChangeEvent<YangInstanceIdentifier, NormalizedNode<?, ?>> change) {
164             if (postSetup) {
165                 receivedChange.set(change);
166             }
167         }
168     }
169
170     public static final WriteTransactionCustomizer simpleWrite(final YangInstanceIdentifier path,
171             final NormalizedNode<?, ?> data) {
172         return new WriteTransactionCustomizer() {
173
174             @Override
175             public void customize(final DOMStoreReadWriteTransaction tx) {
176                 tx.write(path, data);
177             }
178         };
179     }
180
181     public static final WriteTransactionCustomizer simpleMerge(final YangInstanceIdentifier path,
182             final NormalizedNode<?, ?> data) {
183         return new WriteTransactionCustomizer() {
184
185             @Override
186             public void customize(final DOMStoreReadWriteTransaction tx) {
187                 tx.merge(path, data);
188             }
189         };
190     }
191
192     public static final WriteTransactionCustomizer simpleDelete(final YangInstanceIdentifier path) {
193         return new WriteTransactionCustomizer() {
194             @Override
195             public void customize(final DOMStoreReadWriteTransaction tx) {
196                 tx.delete(path);
197             }
198         };
199     }
200 }