blob: 48b4a8706afb01246449e402d6f9b66aac4fa299 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07003 *
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 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.intent;
Ray Milkeye6684082014-10-16 16:59:47 -070017
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -070018import com.google.common.base.MoreObjects;
cansu.toprak409289d2017-10-27 10:04:05 +030019import com.google.common.collect.Sets;
Ray Milkeya7cf8c82018-02-08 15:07:06 -080020import org.onlab.graph.ScalarWeight;
Andrey Komarov2398d962016-09-26 15:11:23 +030021import org.onlab.graph.Weight;
Brian O'Connorabafb502014-12-02 22:26:20 -080022import org.onosproject.core.GroupId;
Luca Pretede10c782017-01-05 17:23:08 -080023import org.onosproject.net.DefaultPath;
Brian O'Connorabafb502014-12-02 22:26:20 -080024import org.onosproject.net.DeviceId;
25import org.onosproject.net.ElementId;
Thomas Vachuskadc91b552016-03-29 14:02:47 -070026import org.onosproject.net.HostId;
Brian O'Connorabafb502014-12-02 22:26:20 -080027import org.onosproject.net.Link;
Ray Milkey5a7787a2015-02-23 11:44:30 -080028import org.onosproject.net.NetTestTools;
Ray Milkey43a28222015-02-23 13:57:58 -080029import org.onosproject.net.NetworkResource;
Brian O'Connorabafb502014-12-02 22:26:20 -080030import org.onosproject.net.Path;
Yi Tseng2a81c9d2016-09-14 10:14:24 -070031import org.onosproject.net.device.DeviceServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080032import org.onosproject.net.flow.FlowId;
33import org.onosproject.net.flow.FlowRule;
jcc3d4e14a2015-04-21 11:32:05 +080034import org.onosproject.net.flow.FlowRuleExtPayLoad;
Carmelo Cascone41605742017-06-19 15:46:44 +090035import org.onosproject.net.flow.IndexTableId;
36import org.onosproject.net.flow.TableId;
Brian O'Connorabafb502014-12-02 22:26:20 -080037import org.onosproject.net.flow.TrafficSelector;
38import org.onosproject.net.flow.TrafficTreatment;
39import org.onosproject.net.flow.criteria.Criterion;
40import org.onosproject.net.flow.criteria.Criterion.Type;
41import org.onosproject.net.flow.instructions.Instruction;
alshabib346b5b32015-03-06 00:42:16 -080042import org.onosproject.net.flow.instructions.Instructions;
Saurav Das86af8f12015-05-25 23:55:33 -070043import org.onosproject.net.flow.instructions.Instructions.MetadataInstruction;
Luca Pretede10c782017-01-05 17:23:08 -080044import org.onosproject.net.provider.ProviderId;
Brian O'Connorabafb502014-12-02 22:26:20 -080045import org.onosproject.net.topology.DefaultTopologyEdge;
46import org.onosproject.net.topology.DefaultTopologyVertex;
Andrey Komarov2398d962016-09-26 15:11:23 +030047import org.onosproject.net.topology.LinkWeigher;
Thomas Vachuska48e64e42015-09-22 15:32:55 -070048import org.onosproject.net.topology.PathServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080049import org.onosproject.net.topology.TopologyVertex;
Ray Milkey5a7787a2015-02-23 11:44:30 -080050import org.onosproject.store.Timestamp;
Ray Milkeye6684082014-10-16 16:59:47 -070051
Luca Pretede10c782017-01-05 17:23:08 -080052import java.util.ArrayList;
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -070053import java.util.Arrays;
54import java.util.Collection;
55import java.util.Collections;
56import java.util.HashSet;
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -070057import java.util.List;
58import java.util.Objects;
59import java.util.Set;
60import java.util.concurrent.atomic.AtomicLong;
61
Thomas Vachuska48e64e42015-09-22 15:32:55 -070062import static org.onosproject.net.NetTestTools.*;
Ray Milkey43a28222015-02-23 13:57:58 -080063
Ray Milkeye6684082014-10-16 16:59:47 -070064/**
65 * Common mocks used by the intent framework tests.
66 */
67public class IntentTestsMocks {
68 /**
69 * Mock traffic selector class used for satisfying API requirements.
70 */
71 public static class MockSelector implements TrafficSelector {
72 @Override
73 public Set<Criterion> criteria() {
74 return new HashSet<>();
75 }
Jonathan Hart936c49d2014-10-23 16:38:59 -070076
77 @Override
78 public Criterion getCriterion(Type type) {
79 return null;
80 }
Ray Milkeye6684082014-10-16 16:59:47 -070081 }
82
83 /**
84 * Mock traffic treatment class used for satisfying API requirements.
85 */
86 public static class MockTreatment implements TrafficTreatment {
87 @Override
alshabib346b5b32015-03-06 00:42:16 -080088 public List<Instruction> deferred() {
Jonathan Hart4a0ba562015-03-23 17:23:33 -070089 return Collections.emptyList();
alshabib346b5b32015-03-06 00:42:16 -080090 }
91
92 @Override
93 public List<Instruction> immediate() {
Jonathan Hart4a0ba562015-03-23 17:23:33 -070094 return Collections.emptyList();
alshabib346b5b32015-03-06 00:42:16 -080095 }
96
97 @Override
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -070098 public List<Instruction> allInstructions() {
Jonathan Hart4a0ba562015-03-23 17:23:33 -070099 return Collections.emptyList();
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -0700100 }
101
102 @Override
alshabib346b5b32015-03-06 00:42:16 -0800103 public Instructions.TableTypeTransition tableTransition() {
104 return null;
105 }
106
107 @Override
Jonathan Hart4a0ba562015-03-23 17:23:33 -0700108 public boolean clearedDeferred() {
109 return false;
alshabib346b5b32015-03-06 00:42:16 -0800110 }
Saurav Das86af8f12015-05-25 23:55:33 -0700111
112 @Override
113 public MetadataInstruction writeMetadata() {
114 return null;
115 }
alshabib10c810b2015-08-18 16:59:04 -0700116
117 @Override
Cem Türker3baff672017-10-12 15:09:01 +0300118 public Instructions.StatTriggerInstruction statTrigger() {
119 return null;
120 }
121
122 @Override
alshabib10c810b2015-08-18 16:59:04 -0700123 public Instructions.MeterInstruction metered() {
124 return null;
125 }
cansu.toprak409289d2017-10-27 10:04:05 +0300126
127 @Override
128 public Set<Instructions.MeterInstruction> meters() {
129 return Sets.newHashSet();
130 }
Ray Milkeye6684082014-10-16 16:59:47 -0700131 }
132
133 /**
134 * Mock path service for creating paths within the test.
135 */
Thomas Vachuska48e64e42015-09-22 15:32:55 -0700136 public static class MockPathService extends PathServiceAdapter {
Ray Milkeye6684082014-10-16 16:59:47 -0700137
138 final String[] pathHops;
139 final String[] reversePathHops;
140
141 /**
142 * Constructor that provides a set of hops to mock.
143 *
144 * @param pathHops path hops to mock
145 */
146 public MockPathService(String[] pathHops) {
147 this.pathHops = pathHops;
148 String[] reversed = pathHops.clone();
149 Collections.reverse(Arrays.asList(reversed));
150 reversePathHops = reversed;
151 }
152
153 @Override
154 public Set<Path> getPaths(ElementId src, ElementId dst) {
155 Set<Path> result = new HashSet<>();
156
157 String[] allHops = new String[pathHops.length];
158
159 if (src.toString().endsWith(pathHops[0])) {
160 System.arraycopy(pathHops, 0, allHops, 0, pathHops.length);
161 } else {
162 System.arraycopy(reversePathHops, 0, allHops, 0, pathHops.length);
163 }
164
Thomas Vachuskadc91b552016-03-29 14:02:47 -0700165 result.add(createPath(src instanceof HostId, dst instanceof HostId, allHops));
Ray Milkeye6684082014-10-16 16:59:47 -0700166 return result;
167 }
168
169 @Override
Andrey Komarov2398d962016-09-26 15:11:23 +0300170 public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeigher weigher) {
171 Set<Path> paths = getPaths(src, dst);
Ray Milkey8d3ce432014-11-07 16:21:10 -0800172
173 for (Path path : paths) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300174 DeviceId srcDevice = path.src().elementId() instanceof DeviceId ? path.src().deviceId() : null;
175 DeviceId dstDevice = path.dst().elementId() instanceof DeviceId ? path.dst().deviceId() : null;
Thomas Vachuskadc91b552016-03-29 14:02:47 -0700176 if (srcDevice != null && dstDevice != null) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300177 TopologyVertex srcVertex = new DefaultTopologyVertex(srcDevice);
178 TopologyVertex dstVertex = new DefaultTopologyVertex(dstDevice);
179 Link link = link(src.toString(), 1, dst.toString(), 1);
Ray Milkey8d3ce432014-11-07 16:21:10 -0800180
Andrey Komarov2398d962016-09-26 15:11:23 +0300181 Weight weightValue = weigher.weight(new DefaultTopologyEdge(srcVertex, dstVertex, link));
182 if (weightValue.isNegative()) {
Thomas Vachuskadc91b552016-03-29 14:02:47 -0700183 return new HashSet<>();
184 }
Ray Milkey8d3ce432014-11-07 16:21:10 -0800185 }
186 }
187 return paths;
Ray Milkeye6684082014-10-16 16:59:47 -0700188 }
189 }
Ray Milkey8d3ce432014-11-07 16:21:10 -0800190
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700191 /**
192 * Mock path service for creating paths within the test.
193 *
194 */
Luca Pretede10c782017-01-05 17:23:08 -0800195 public static class Mp2MpMockPathService extends PathServiceAdapter {
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700196
197 final String[] pathHops;
198 final String[] reversePathHops;
199
200 /**
201 * Constructor that provides a set of hops to mock.
202 *
203 * @param pathHops path hops to mock
204 */
205 public Mp2MpMockPathService(String[] pathHops) {
206 this.pathHops = pathHops;
207 String[] reversed = pathHops.clone();
208 Collections.reverse(Arrays.asList(reversed));
209 reversePathHops = reversed;
210 }
211
212 @Override
213 public Set<Path> getPaths(ElementId src, ElementId dst) {
214 Set<Path> result = new HashSet<>();
215
216 String[] allHops = new String[pathHops.length + 2];
217 allHops[0] = src.toString();
218 allHops[allHops.length - 1] = dst.toString();
219
220 if (pathHops.length != 0) {
221 System.arraycopy(pathHops, 0, allHops, 1, pathHops.length);
222 }
223
224 result.add(createPath(allHops));
225
226 return result;
227 }
228
229 @Override
Andrey Komarov2398d962016-09-26 15:11:23 +0300230 public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeigher weigher) {
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700231 final Set<Path> paths = getPaths(src, dst);
232
233 for (Path path : paths) {
234 final DeviceId srcDevice = path.src().elementId() instanceof DeviceId ? path.src().deviceId() : null;
235 final DeviceId dstDevice = path.dst().elementId() instanceof DeviceId ? path.dst().deviceId() : null;
236 if (srcDevice != null && dstDevice != null) {
237 final TopologyVertex srcVertex = new DefaultTopologyVertex(srcDevice);
238 final TopologyVertex dstVertex = new DefaultTopologyVertex(dstDevice);
239 final Link link = link(src.toString(), 1, dst.toString(), 1);
240
Andrey Komarov2398d962016-09-26 15:11:23 +0300241 final Weight weightValue = weigher.weight(new DefaultTopologyEdge(srcVertex, dstVertex, link));
242 if (weightValue.isNegative()) {
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700243 return new HashSet<>();
244 }
245 }
246 }
247 return paths;
248 }
249 }
250
Luca Pretede10c782017-01-05 17:23:08 -0800251 /**
252 * Mock path service for creating paths for MP2SP intent tests, returning
253 * pre-determined paths.
254 */
255 public static class FixedMP2MPMockPathService extends PathServiceAdapter {
Sho SHIMIZUb1681bd2016-02-22 12:47:50 -0800256
Luca Pretede10c782017-01-05 17:23:08 -0800257 final String[] pathHops;
Sho SHIMIZUb1681bd2016-02-22 12:47:50 -0800258
Luca Pretede10c782017-01-05 17:23:08 -0800259 public static final String DPID_1 = "of:s1";
260 public static final String DPID_2 = "of:s2";
261 public static final String DPID_3 = "of:s3";
262 public static final String DPID_4 = "of:s4";
Sho SHIMIZUb1681bd2016-02-22 12:47:50 -0800263
Luca Pretede10c782017-01-05 17:23:08 -0800264 /**
265 * Constructor that provides a set of hops to mock.
266 *
267 * @param pathHops path hops to mock
268 */
269 public FixedMP2MPMockPathService(String[] pathHops) {
270 this.pathHops = pathHops;
Ray Milkey8d3ce432014-11-07 16:21:10 -0800271 }
272
HIGUCHI Yutaca9cc8e2015-10-29 23:26:51 -0700273 @Override
Luca Pretede10c782017-01-05 17:23:08 -0800274 public Set<Path> getPaths(ElementId src, ElementId dst) {
275 List<Link> links = new ArrayList<>();
276 Set<Path> result = new HashSet<>();
277 ProviderId providerId = new ProviderId("of", "foo");
278 DefaultPath path;
279 if (src.toString().equals(DPID_1) && dst.toString().equals(DPID_4)) {
280 links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 1));
281 links.add(NetTestTools.linkNoPrefixes(pathHops[0], 2, dst.toString(), 1));
282 } else if (src.toString().equals(DPID_2) && dst.toString().equals(DPID_4)) {
283 links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 3));
284 links.add(NetTestTools.linkNoPrefixes(pathHops[0], 2, dst.toString(), 1));
285 } else if (src.toString().equals(DPID_4) && dst.toString().equals(DPID_1)) {
286 links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 1));
287 links.add(NetTestTools.linkNoPrefixes(pathHops[0], 2, dst.toString(), 1));
288 } else if (src.toString().equals(DPID_4) && dst.toString().equals(DPID_2)) {
289 links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 1));
290 links.add(NetTestTools.linkNoPrefixes(pathHops[0], 3, dst.toString(), 1));
291 } else {
292 return result;
Ray Milkey8d3ce432014-11-07 16:21:10 -0800293 }
Ray Milkeya7cf8c82018-02-08 15:07:06 -0800294 path = new DefaultPath(providerId, links, ScalarWeight.toWeight(3));
Luca Pretede10c782017-01-05 17:23:08 -0800295 result.add(path);
Ray Milkey8d3ce432014-11-07 16:21:10 -0800296
Luca Pretede10c782017-01-05 17:23:08 -0800297 return result;
Ray Milkey8d3ce432014-11-07 16:21:10 -0800298 }
299
300 @Override
Luca Pretede10c782017-01-05 17:23:08 -0800301 public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeigher weigher) {
302 final Set<Path> paths = getPaths(src, dst);
Ray Milkey8d3ce432014-11-07 16:21:10 -0800303
Luca Pretede10c782017-01-05 17:23:08 -0800304 for (Path path : paths) {
305 final DeviceId srcDevice = path.src().elementId() instanceof DeviceId ? path.src().deviceId() : null;
306 final DeviceId dstDevice = path.dst().elementId() instanceof DeviceId ? path.dst().deviceId() : null;
307 if (srcDevice != null && dstDevice != null) {
308 final TopologyVertex srcVertex = new DefaultTopologyVertex(srcDevice);
309 final TopologyVertex dstVertex = new DefaultTopologyVertex(dstDevice);
310 final Link link = link(src.toString(), 1, dst.toString(), 1);
311
312 final Weight weightValue = weigher.weight(new DefaultTopologyEdge(srcVertex, dstVertex, link));
313 if (weightValue.isNegative()) {
314 return new HashSet<>();
315 }
316 }
317 }
318 return paths;
Ray Milkeye97ede92014-11-20 10:43:12 -0800319 }
Ray Milkey8d3ce432014-11-07 16:21:10 -0800320 }
321
Ray Milkey930fc662014-11-11 16:07:45 -0800322 private static final IntentTestsMocks.MockSelector SELECTOR =
323 new IntentTestsMocks.MockSelector();
324 private static final IntentTestsMocks.MockTreatment TREATMENT =
325 new IntentTestsMocks.MockTreatment();
326
327 public static class MockFlowRule implements FlowRule {
Ray Milkey77a455f2015-03-27 10:08:17 -0700328 static int nextId = 0;
Ray Milkey930fc662014-11-11 16:07:45 -0800329
330 int priority;
Carmelo Cascone41605742017-06-19 15:46:44 +0900331 IndexTableId tableId;
Ray Milkey77a455f2015-03-27 10:08:17 -0700332 long timestamp;
333 int id;
jcc3d4e14a2015-04-21 11:32:05 +0800334 FlowRuleExtPayLoad payLoad;
sangho11c30ac2015-01-22 14:30:55 -0800335
Ray Milkey930fc662014-11-11 16:07:45 -0800336 public MockFlowRule(int priority) {
337 this.priority = priority;
Carmelo Cascone41605742017-06-19 15:46:44 +0900338 this.tableId = DEFAULT_TABLE;
Ray Milkey77a455f2015-03-27 10:08:17 -0700339 this.timestamp = System.currentTimeMillis();
340 this.id = nextId++;
jcc3d4e14a2015-04-21 11:32:05 +0800341 this.payLoad = null;
342 }
343
344 public MockFlowRule(int priority, FlowRuleExtPayLoad payLoad) {
345 this.priority = priority;
346 this.timestamp = System.currentTimeMillis();
347 this.id = nextId++;
348 this.payLoad = payLoad;
Ray Milkey930fc662014-11-11 16:07:45 -0800349 }
350
351 @Override
352 public FlowId id() {
Ray Milkey77a455f2015-03-27 10:08:17 -0700353 return FlowId.valueOf(id);
Ray Milkey930fc662014-11-11 16:07:45 -0800354 }
355
356 @Override
357 public short appId() {
358 return 0;
359 }
360
361 @Override
Sho SHIMIZU75a5bd92014-11-25 11:22:56 -0800362 public GroupId groupId() {
Yi Tsengfa394de2017-02-01 11:26:40 -0800363 return new GroupId(0);
alshabib28204e52014-11-12 18:29:45 -0800364 }
365
366 @Override
Ray Milkey930fc662014-11-11 16:07:45 -0800367 public int priority() {
368 return priority;
369 }
370
371 @Override
372 public DeviceId deviceId() {
373 return did("1");
374 }
375
376 @Override
377 public TrafficSelector selector() {
378 return SELECTOR;
379 }
380
381 @Override
382 public TrafficTreatment treatment() {
383 return TREATMENT;
384 }
385
386 @Override
387 public int timeout() {
388 return 0;
389 }
390
391 @Override
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700392 public int hardTimeout() {
393 return 0;
394 }
395
396 @Override
397 public FlowRemoveReason reason() {
398 return FlowRemoveReason.NO_REASON;
399 }
400
401 @Override
Ray Milkey930fc662014-11-11 16:07:45 -0800402 public boolean isPermanent() {
403 return false;
404 }
405
Brian O'Connor427a1762014-11-19 18:40:32 -0800406 @Override
407 public int hashCode() {
HIGUCHI Yutaca9cc8e2015-10-29 23:26:51 -0700408 return priority;
Brian O'Connor427a1762014-11-19 18:40:32 -0800409 }
Ray Milkey930fc662014-11-11 16:07:45 -0800410
Brian O'Connor427a1762014-11-19 18:40:32 -0800411 @Override
412 public boolean equals(Object obj) {
413 if (this == obj) {
414 return true;
415 }
416 if (obj == null || getClass() != obj.getClass()) {
417 return false;
418 }
419 final MockFlowRule other = (MockFlowRule) obj;
Ray Milkey77a455f2015-03-27 10:08:17 -0700420 return Objects.equals(this.timestamp, other.timestamp) &&
Nikhil Cheerla2ec191f2015-07-09 12:34:54 -0700421 this.id == other.id;
Brian O'Connor427a1762014-11-19 18:40:32 -0800422 }
sangho11c30ac2015-01-22 14:30:55 -0800423
424 @Override
Jonathan Hartf44e42c2015-08-04 09:58:46 -0700425 public boolean exactMatch(FlowRule rule) {
426 return this.equals(rule);
427 }
428
429 @Override
alshabibdb774072015-04-20 13:13:51 -0700430 public int tableId() {
Carmelo Cascone41605742017-06-19 15:46:44 +0900431 return tableId.id();
432 }
433
434 @Override
435 public TableId table() {
alshabib08d98982015-04-21 16:25:50 -0700436 return tableId;
alshabibdb774072015-04-20 13:13:51 -0700437 }
jcc3d4e14a2015-04-21 11:32:05 +0800438
439 @Override
440 public FlowRuleExtPayLoad payLoad() {
441 return payLoad;
442 }
Ray Milkey930fc662014-11-11 16:07:45 -0800443 }
444
Ray Milkey5a7787a2015-02-23 11:44:30 -0800445 public static class MockIntent extends Intent {
446 private static AtomicLong counter = new AtomicLong(0);
447
448 private final Long number;
449
450 public MockIntent(Long number) {
Ray Milkeyebc5d222015-03-18 15:45:36 -0700451 super(NetTestTools.APP_ID, null, Collections.emptyList(),
Ray Milkey39f78b62018-01-05 15:17:37 -0800452 Intent.DEFAULT_INTENT_PRIORITY, null);
Ray Milkey5a7787a2015-02-23 11:44:30 -0800453 this.number = number;
454 }
455
Ray Milkey43a28222015-02-23 13:57:58 -0800456 public MockIntent(Long number, Collection<NetworkResource> resources) {
Ray Milkey39f78b62018-01-05 15:17:37 -0800457 super(NetTestTools.APP_ID, null, resources, Intent.DEFAULT_INTENT_PRIORITY, null);
Ray Milkey43a28222015-02-23 13:57:58 -0800458 this.number = number;
459 }
460
Ray Milkey5a7787a2015-02-23 11:44:30 -0800461 public Long number() {
462 return number;
463 }
464
465 public static Long nextId() {
466 return counter.getAndIncrement();
467 }
Ray Milkey43a28222015-02-23 13:57:58 -0800468
469 @Override
470 public String toString() {
471 return MoreObjects.toStringHelper(getClass())
472 .add("id", id())
473 .add("appId", appId())
474 .toString();
475 }
Ray Milkey5a7787a2015-02-23 11:44:30 -0800476 }
477
478 public static class MockTimestamp implements Timestamp {
479 final int value;
480
481 public MockTimestamp(int value) {
482 this.value = value;
483 }
484
485 @Override
486 public int compareTo(Timestamp o) {
487 if (!(o instanceof MockTimestamp)) {
488 return -1;
489 }
490 MockTimestamp that = (MockTimestamp) o;
Jonathan Hart72175c22015-03-24 18:55:58 -0700491 return this.value - that.value;
Ray Milkey5a7787a2015-02-23 11:44:30 -0800492 }
Yuta HIGUCHI4f8a3772017-05-16 20:23:49 -0700493
494 @Override
495 public int hashCode() {
496 return value;
497 }
498
499 @Override
500 public boolean equals(Object obj) {
501 if (obj instanceof MockTimestamp) {
502 return this.compareTo((MockTimestamp) obj) == 0;
503 }
504 return false;
505 }
Ray Milkey5a7787a2015-02-23 11:44:30 -0800506 }
507
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700508 /**
509 * Mocks the device service so that a device appears available in the test.
510 */
511 public static class MockDeviceService extends DeviceServiceAdapter {
512 @Override
513 public boolean isAvailable(DeviceId deviceId) {
514 return true;
515 }
516 }
Ray Milkeye6684082014-10-16 16:59:47 -0700517}