Ray Milkey
Committed by Gerrit Code Review

Unit test for the gossip intent store

This change also implements a unit test harness for the
EventuallyConsistentMap that is intended to be reusable
to test other stores.

Change-Id: I2257da9b19412b97a3aa0f127be7263a7732b852
...@@ -18,19 +18,25 @@ package org.onosproject.cluster; ...@@ -18,19 +18,25 @@ package org.onosproject.cluster;
18 import java.util.Set; 18 import java.util.Set;
19 19
20 import org.joda.time.DateTime; 20 import org.joda.time.DateTime;
21 +import org.onlab.packet.IpAddress;
22 +
23 +import com.google.common.collect.ImmutableSet;
21 24
22 /** 25 /**
23 * Test adapter for the cluster service. 26 * Test adapter for the cluster service.
24 */ 27 */
25 public class ClusterServiceAdapter implements ClusterService { 28 public class ClusterServiceAdapter implements ClusterService {
29 + ControllerNode local = new DefaultControllerNode(new NodeId("local"),
30 + IpAddress.valueOf("127.0.0.1"));
31 +
26 @Override 32 @Override
27 public ControllerNode getLocalNode() { 33 public ControllerNode getLocalNode() {
28 - return null; 34 + return local;
29 } 35 }
30 36
31 @Override 37 @Override
32 public Set<ControllerNode> getNodes() { 38 public Set<ControllerNode> getNodes() {
33 - return null; 39 + return ImmutableSet.of(local);
34 } 40 }
35 41
36 @Override 42 @Override
......
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
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 +package org.onosproject.net.intent;
17 +
18 +import org.onosproject.cluster.NodeId;
19 +
20 +import static org.junit.Assert.*;
21 +
22 +/**
23 + * Testing adapter for the partition service.
24 + */
25 +public class PartitionServiceAdapter implements PartitionService {
26 + @Override
27 + public boolean isMine(Key intentKey) {
28 + return true;
29 + }
30 +
31 + @Override
32 + public NodeId getLeader(Key intentKey) {
33 + return null;
34 + }
35 +
36 + @Override
37 + public void addListener(PartitionEventListener listener) {
38 +
39 + }
40 +
41 + @Override
42 + public void removeListener(PartitionEventListener listener) {
43 +
44 + }
45 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
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 +package org.onosproject.store.service;
17 +
18 +import java.util.Collection;
19 +import java.util.Map;
20 +import java.util.Set;
21 +import java.util.function.BiFunction;
22 +
23 +/**
24 + * Testing adapter for EventuallyConsistentMap.
25 + */
26 +public class EventuallyConsistentMapAdapter<K, V> implements EventuallyConsistentMap<K, V> {
27 + @Override
28 + public int size() {
29 + return 0;
30 + }
31 +
32 + @Override
33 + public boolean isEmpty() {
34 + return false;
35 + }
36 +
37 + @Override
38 + public boolean containsKey(K key) {
39 + return false;
40 + }
41 +
42 + @Override
43 + public boolean containsValue(V value) {
44 + return false;
45 + }
46 +
47 + @Override
48 + public V get(K key) {
49 + return null;
50 + }
51 +
52 + @Override
53 + public void put(K key, V value) {
54 +
55 + }
56 +
57 + @Override
58 + public V remove(K key) {
59 + return null;
60 + }
61 +
62 + @Override
63 + public void remove(K key, V value) {
64 +
65 + }
66 +
67 + @Override
68 + public V compute(K key, BiFunction<K, V, V> recomputeFunction) {
69 + return null;
70 + }
71 +
72 + @Override
73 + public void putAll(Map<? extends K, ? extends V> m) {
74 +
75 + }
76 +
77 + @Override
78 + public void clear() {
79 +
80 + }
81 +
82 + @Override
83 + public Set<K> keySet() {
84 + return null;
85 + }
86 +
87 + @Override
88 + public Collection<V> values() {
89 + return null;
90 + }
91 +
92 + @Override
93 + public Set<Map.Entry<K, V>> entrySet() {
94 + return null;
95 + }
96 +
97 + @Override
98 + public void addListener(EventuallyConsistentMapListener<K, V> listener) {
99 +
100 + }
101 +
102 + @Override
103 + public void removeListener(EventuallyConsistentMapListener<K, V> listener) {
104 +
105 + }
106 +
107 + @Override
108 + public void destroy() {
109 +
110 + }
111 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
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 +package org.onosproject.store.service;
17 +
18 +/**
19 + * Adapter for the storage service.
20 + */
21 +public class StorageServiceAdapter implements StorageService {
22 + @Override
23 + public <K, V> EventuallyConsistentMapBuilder<K, V> eventuallyConsistentMapBuilder() {
24 + return null;
25 + }
26 +
27 + @Override
28 + public <K, V> ConsistentMapBuilder<K, V> consistentMapBuilder() {
29 + return null;
30 + }
31 +
32 + @Override
33 + public <E> DistributedSetBuilder<E> setBuilder() {
34 + return null;
35 + }
36 +
37 + @Override
38 + public <E> DistributedQueueBuilder<E> queueBuilder() {
39 + return null;
40 + }
41 +
42 + @Override
43 + public AtomicCounterBuilder atomicCounterBuilder() {
44 + return null;
45 + }
46 +
47 + @Override
48 + public <V> AtomicValueBuilder<V> atomicValueBuilder() {
49 + return null;
50 + }
51 +
52 + @Override
53 + public TransactionContextBuilder transactionContextBuilder() {
54 + return null;
55 + }
56 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
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 +package org.onosproject.store.service;
17 +
18 +import java.util.Collection;
19 +import java.util.HashMap;
20 +import java.util.LinkedList;
21 +import java.util.List;
22 +import java.util.Map;
23 +import java.util.Set;
24 +import java.util.concurrent.ExecutorService;
25 +import java.util.concurrent.ScheduledExecutorService;
26 +import java.util.concurrent.TimeUnit;
27 +import java.util.function.BiFunction;
28 +
29 +import org.onlab.util.KryoNamespace;
30 +import org.onosproject.cluster.NodeId;
31 +import org.onosproject.store.Timestamp;
32 +
33 +import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.*;
34 +
35 +/**
36 + * Testing version of an Eventually Consistent Map.
37 + */
38 +
39 +public final class TestEventuallyConsistentMap<K, V> extends EventuallyConsistentMapAdapter<K, V> {
40 +
41 + private final HashMap<K, V> map;
42 + private final String mapName;
43 + private final List<EventuallyConsistentMapListener<K, V>> listeners;
44 + private final BiFunction<K, V, Collection<NodeId>> peerUpdateFunction;
45 +
46 + private TestEventuallyConsistentMap(String mapName,
47 + BiFunction<K, V, Collection<NodeId>> peerUpdateFunction) {
48 + map = new HashMap<>();
49 + listeners = new LinkedList<>();
50 + this.mapName = mapName;
51 + this.peerUpdateFunction = peerUpdateFunction;
52 + }
53 +
54 + /**
55 + * Notify all listeners of an event.
56 + */
57 + private void notifyListeners(EventuallyConsistentMapEvent<K, V> event) {
58 + listeners.forEach(
59 + listener -> listener.event(event)
60 + );
61 + }
62 +
63 + @Override
64 + public int size() {
65 + return map.size();
66 + }
67 +
68 + @Override
69 + public boolean isEmpty() {
70 + return map.isEmpty();
71 + }
72 +
73 + @Override
74 + public boolean containsKey(K key) {
75 + return map.containsKey(key);
76 + }
77 +
78 + @Override
79 + public boolean containsValue(V value) {
80 + return map.containsValue(value);
81 + }
82 +
83 + @Override
84 + public V get(K key) {
85 + return map.get(key);
86 + }
87 +
88 + @Override
89 + public void put(K key, V value) {
90 + map.put(key, value);
91 + EventuallyConsistentMapEvent<K, V> addEvent =
92 + new EventuallyConsistentMapEvent<>(mapName, PUT, key, value);
93 + notifyListeners(addEvent);
94 + peerUpdateFunction.apply(key, value);
95 + }
96 +
97 + @Override
98 + public V remove(K key) {
99 + V result = map.remove(key);
100 + if (result != null) {
101 + EventuallyConsistentMapEvent<K, V> removeEvent =
102 + new EventuallyConsistentMapEvent<>(mapName, REMOVE,
103 + key, map.get(key));
104 + notifyListeners(removeEvent);
105 + }
106 + return result;
107 + }
108 +
109 + @Override
110 + public void remove(K key, V value) {
111 + boolean removed = map.remove(key, value);
112 + if (removed) {
113 + EventuallyConsistentMapEvent<K, V> removeEvent =
114 + new EventuallyConsistentMapEvent<>(mapName, REMOVE, key, value);
115 + notifyListeners(removeEvent);
116 + }
117 + }
118 +
119 + @Override
120 + public V compute(K key, BiFunction<K, V, V> recomputeFunction) {
121 + return map.compute(key, recomputeFunction);
122 + }
123 +
124 + @Override
125 + public void putAll(Map<? extends K, ? extends V> m) {
126 + map.putAll(m);
127 + }
128 +
129 + @Override
130 + public void clear() {
131 + map.clear();
132 + }
133 +
134 + @Override
135 + public Set<K> keySet() {
136 + return map.keySet();
137 + }
138 +
139 + @Override
140 + public Collection<V> values() {
141 + return map.values();
142 + }
143 +
144 + @Override
145 + public Set<Map.Entry<K, V>> entrySet() {
146 + return map.entrySet();
147 + }
148 +
149 + public static <K, V> Builder<K, V> builder() {
150 + return new Builder<>();
151 + }
152 +
153 + @Override
154 + public void addListener(EventuallyConsistentMapListener<K, V> listener) {
155 + listeners.add(listener);
156 + }
157 +
158 + @Override
159 + public void removeListener(EventuallyConsistentMapListener<K, V> listener) {
160 + listeners.remove(listener);
161 + }
162 +
163 + public static class Builder<K, V> implements EventuallyConsistentMapBuilder<K, V> {
164 + private String name;
165 + private BiFunction<K, V, Collection<NodeId>> peerUpdateFunction;
166 +
167 + @Override
168 + public EventuallyConsistentMapBuilder<K, V> withName(String name) {
169 + this.name = name;
170 + return this;
171 + }
172 +
173 + @Override
174 + public EventuallyConsistentMapBuilder<K, V> withSerializer(KryoNamespace.Builder serializerBuilder) {
175 + return this;
176 + }
177 +
178 + @Override
179 + public EventuallyConsistentMapBuilder<K, V>
180 + withTimestampProvider(BiFunction<K, V, Timestamp> timestampProvider) {
181 + return this;
182 + }
183 +
184 + @Override
185 + public EventuallyConsistentMapBuilder<K, V> withEventExecutor(ExecutorService executor) {
186 + return this;
187 + }
188 +
189 + @Override
190 + public EventuallyConsistentMapBuilder<K, V> withCommunicationExecutor(ExecutorService executor) {
191 + return this;
192 + }
193 +
194 + @Override
195 + public EventuallyConsistentMapBuilder<K, V> withBackgroundExecutor(ScheduledExecutorService executor) {
196 + return this;
197 + }
198 +
199 + @Override
200 + public EventuallyConsistentMapBuilder<K, V>
201 + withPeerUpdateFunction(BiFunction<K, V, Collection<NodeId>> peerUpdateFunction) {
202 + this.peerUpdateFunction = peerUpdateFunction;
203 + return this;
204 + }
205 +
206 + @Override
207 + public EventuallyConsistentMapBuilder<K, V> withTombstonesDisabled() {
208 + return this;
209 + }
210 +
211 + @Override
212 + public EventuallyConsistentMapBuilder<K, V> withAntiEntropyPeriod(long period, TimeUnit unit) {
213 + return this;
214 + }
215 +
216 + @Override
217 + public EventuallyConsistentMapBuilder<K, V> withFasterConvergence() {
218 + return this;
219 + }
220 +
221 + @Override
222 + public EventuallyConsistentMapBuilder<K, V> withPersistence() {
223 + return this;
224 + }
225 +
226 + @Override
227 + public EventuallyConsistentMap<K, V> build() {
228 + if (name == null) {
229 + name = "test";
230 + }
231 + return new TestEventuallyConsistentMap<>(name, peerUpdateFunction);
232 + }
233 + }
234 +
235 +}
236 +
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
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 +package org.onosproject.store.service;
17 +
18 +public class TestStorageService extends StorageServiceAdapter {
19 +
20 +
21 + @Override
22 + public <K, V> EventuallyConsistentMapBuilder<K, V> eventuallyConsistentMapBuilder() {
23 + return TestEventuallyConsistentMap.builder();
24 + }
25 +
26 + @Override
27 + public <K, V> ConsistentMapBuilder<K, V> consistentMapBuilder() {
28 + throw new UnsupportedOperationException("consistentMapBuilder");
29 + }
30 +
31 + @Override
32 + public <E> DistributedSetBuilder<E> setBuilder() {
33 + throw new UnsupportedOperationException("setBuilder");
34 + }
35 +
36 + @Override
37 + public <E> DistributedQueueBuilder<E> queueBuilder() {
38 + throw new UnsupportedOperationException("queueBuilder");
39 + }
40 +
41 + @Override
42 + public AtomicCounterBuilder atomicCounterBuilder() {
43 + throw new UnsupportedOperationException("atomicCounterBuilder");
44 + }
45 +
46 + @Override
47 + public <V> AtomicValueBuilder<V> atomicValueBuilder() {
48 + throw new UnsupportedOperationException("atomicValueBuilder");
49 + }
50 +
51 + @Override
52 + public TransactionContextBuilder transactionContextBuilder() {
53 + throw new UnsupportedOperationException("transactionContextBuilder");
54 + }
55 +}
1 +/*
2 + * Copyright 2015 Open Networking Laboratory
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 +package org.onosproject.store.intent.impl;
17 +
18 +import java.util.LinkedList;
19 +import java.util.List;
20 +import java.util.stream.IntStream;
21 +
22 +import org.junit.After;
23 +import org.junit.Before;
24 +import org.junit.Test;
25 +import org.onosproject.cluster.ClusterServiceAdapter;
26 +import org.onosproject.core.IdGenerator;
27 +import org.onosproject.net.intent.HostToHostIntent;
28 +import org.onosproject.net.intent.Intent;
29 +import org.onosproject.net.intent.IntentData;
30 +import org.onosproject.net.intent.IntentState;
31 +import org.onosproject.net.intent.IntentTestsMocks;
32 +import org.onosproject.net.intent.MockIdGenerator;
33 +import org.onosproject.net.intent.PartitionServiceAdapter;
34 +import org.onosproject.store.service.TestStorageService;
35 +
36 +import static org.hamcrest.Matchers.is;
37 +import static org.hamcrest.Matchers.nullValue;
38 +import static org.junit.Assert.assertThat;
39 +import static org.onosproject.net.NetTestTools.APP_ID;
40 +import static org.onosproject.net.NetTestTools.hid;
41 +
42 +/**
43 + * Gossip Intent Store test using database adapter.
44 + */
45 +public class GossipIntentStoreTest {
46 +
47 + private GossipIntentStore intentStore;
48 + private IdGenerator idGenerator;
49 + private HostToHostIntent.Builder builder1;
50 +
51 + @Before
52 + public void setUp() {
53 + intentStore = new GossipIntentStore();
54 + intentStore.storageService = new TestStorageService();
55 + intentStore.partitionService = new PartitionServiceAdapter();
56 + intentStore.clusterService = new ClusterServiceAdapter();
57 + idGenerator = new MockIdGenerator();
58 + Intent.bindIdGenerator(idGenerator);
59 + builder1 = HostToHostIntent
60 + .builder()
61 + .one(hid("12:34:56:78:91:ab/1"))
62 + .two(hid("12:34:56:78:91:ac/1"))
63 + .appId(APP_ID);
64 + intentStore.activate();
65 + }
66 +
67 + @After
68 + public void cleanUp() {
69 + intentStore.deactivate();
70 + Intent.unbindIdGenerator(idGenerator);
71 + }
72 +
73 + /**
74 + * Generates a list of test intent data.
75 + *
76 + * @param count how many intent data objects are needed
77 + * @return list of intent data
78 + */
79 + private List<IntentData> generateIntentList(int count) {
80 + LinkedList<IntentData> intents = new LinkedList<>();
81 + IntStream.rangeClosed(1, count)
82 + .forEach(i ->
83 + intents.add(
84 + new IntentData(
85 + builder1
86 + .priority(i)
87 + .build(),
88 + IntentState.INSTALLED,
89 + new IntentTestsMocks.MockTimestamp(12))));
90 + return intents;
91 + }
92 +
93 + /**
94 + * Tests the intent count APIs.
95 + */
96 + @Test
97 + public void testGetIntentCount() {
98 + assertThat(intentStore.getIntentCount(), is(0L));
99 +
100 + generateIntentList(5).forEach(intentStore::write);
101 +
102 + assertThat(intentStore.getIntentCount(), is(5L));
103 + }
104 +
105 + /**
106 + * Tests the batch add API.
107 + */
108 + @Test
109 + public void testBatchAdd() {
110 + assertThat(intentStore.getIntentCount(), is(0L));
111 +
112 + List<IntentData> intents = generateIntentList(5);
113 +
114 + intentStore.batchWrite(intents);
115 + assertThat(intentStore.getIntentCount(), is(5L));
116 + }
117 +
118 +
119 + /**
120 + * Tests adding and withdrawing an Intent.
121 + */
122 + @Test
123 + public void testAddAndWithdrawIntent() {
124 + // build and install one intent
125 + Intent intent = builder1.build();
126 + IntentData installed = new IntentData(
127 + intent,
128 + IntentState.INSTALLED,
129 + new IntentTestsMocks.MockTimestamp(12));
130 + intentStore.write(installed);
131 +
132 + // check that the intent count includes the new one
133 + assertThat(intentStore.getIntentCount(), is(1L));
134 +
135 + // check that the getIntents() API returns the new intent
136 + intentStore.getIntents()
137 + .forEach(item -> assertThat(item, is(intent)));
138 +
139 + // check that the getInstallableIntents() API returns the new intent
140 + intentStore.getInstallableIntents(intent.key())
141 + .forEach(item -> assertThat(item, is(intent)));
142 +
143 + // check that the getIntent() API can find the new intent
144 + Intent queried = intentStore.getIntent(intent.key());
145 + assertThat(queried, is(intent));
146 +
147 + // check that the state of the new intent is correct
148 + IntentState state = intentStore.getIntentState(intent.key());
149 + assertThat(state, is(IntentState.INSTALLED));
150 +
151 + // check that the getIntentData() API returns the proper value for the
152 + // new intent
153 + IntentData dataByQuery = intentStore.getIntentData(intent.key());
154 + assertThat(dataByQuery, is(installed));
155 +
156 + // check that the getIntentData() API returns the new intent when given
157 + // a time stamp to look for
158 + Iterable<IntentData> dataIteratorByTime = intentStore.getIntentData(true, 10L);
159 + assertThat(dataIteratorByTime.iterator().hasNext(), is(true));
160 + dataIteratorByTime.forEach(
161 + data -> assertThat(data, is(installed))
162 + );
163 +
164 + // check that the getIntentData() API returns the new intent when asked to
165 + // find all intents
166 + Iterable<IntentData> dataIteratorAll = intentStore.getIntentData(false, 0L);
167 + assertThat(dataIteratorAll.iterator().hasNext(), is(true));
168 + dataIteratorAll.forEach(
169 + data -> assertThat(data, is(installed))
170 + );
171 +
172 + // now purge the intent that was created
173 + IntentData purge = new IntentData(
174 + intent,
175 + IntentState.PURGE_REQ,
176 + new IntentTestsMocks.MockTimestamp(12));
177 + intentStore.write(purge);
178 +
179 + // check that no intents are left
180 + assertThat(intentStore.getIntentCount(), is(0L));
181 +
182 + // check that a getIntent() operation on the key of the purged intent
183 + // returns null
184 + Intent queriedAfterWithdrawal = intentStore.getIntent(intent.key());
185 + assertThat(queriedAfterWithdrawal, nullValue());
186 + }
187 +
188 + /**
189 + * Tests the operation of the APIs for the pending map.
190 + */
191 + @Test
192 + public void testPending() {
193 + // crete a new intent and add it as pending
194 + Intent intent = builder1.build();
195 + IntentData installed = new IntentData(
196 + intent,
197 + IntentState.INSTALLED,
198 + new IntentTestsMocks.MockTimestamp(11));
199 + intentStore.addPending(installed);
200 +
201 + // check that the getPending() API returns the new pending intent
202 + Iterable<Intent> pendingIntentIteratorAll = intentStore.getPending();
203 + assertThat(pendingIntentIteratorAll.iterator().hasNext(), is(true));
204 + pendingIntentIteratorAll.forEach(
205 + data -> assertThat(data, is(intent))
206 + );
207 +
208 + // check that the getPendingData() API returns the IntentData for the
209 + // new pending intent
210 + Iterable<IntentData> pendingDataIteratorAll = intentStore.getPendingData();
211 + assertThat(pendingDataIteratorAll.iterator().hasNext(), is(true));
212 + pendingDataIteratorAll.forEach(
213 + data -> assertThat(data, is(installed))
214 + );
215 +
216 + // check that the new pending intent is returned by the getPendingData()
217 + // API when a time stamp is provided
218 + Iterable<IntentData> pendingDataIteratorSelected =
219 + intentStore.getPendingData(true, 10L);
220 + assertThat(pendingDataIteratorSelected.iterator().hasNext(), is(true));
221 + pendingDataIteratorSelected.forEach(
222 + data -> assertThat(data, is(installed))
223 + );
224 +
225 + // check that the new pending intent is returned by the getPendingData()
226 + // API when a time stamp is provided
227 + Iterable<IntentData> pendingDataIteratorAllFromTimestamp =
228 + intentStore.getPendingData(false, 0L);
229 + assertThat(pendingDataIteratorAllFromTimestamp.iterator().hasNext(), is(true));
230 + pendingDataIteratorSelected.forEach(
231 + data -> assertThat(data, is(installed))
232 + );
233 + }
234 +}