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