blob: 90cc69715bc63db93a529a026337926232cc9a60 [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;
Andrey Komarov2398d962016-09-26 15:11:23 +030020import org.onlab.graph.Weight;
Brian O'Connorabafb502014-12-02 22:26:20 -080021import org.onosproject.core.GroupId;
Luca Pretede10c782017-01-05 17:23:08 -080022import org.onosproject.net.DefaultPath;
Brian O'Connorabafb502014-12-02 22:26:20 -080023import org.onosproject.net.DeviceId;
24import org.onosproject.net.ElementId;
Thomas Vachuskadc91b552016-03-29 14:02:47 -070025import org.onosproject.net.HostId;
Brian O'Connorabafb502014-12-02 22:26:20 -080026import org.onosproject.net.Link;
Ray Milkey5a7787a2015-02-23 11:44:30 -080027import org.onosproject.net.NetTestTools;
Ray Milkey43a28222015-02-23 13:57:58 -080028import org.onosproject.net.NetworkResource;
Brian O'Connorabafb502014-12-02 22:26:20 -080029import org.onosproject.net.Path;
Yi Tseng2a81c9d2016-09-14 10:14:24 -070030import org.onosproject.net.device.DeviceServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080031import org.onosproject.net.flow.FlowId;
32import org.onosproject.net.flow.FlowRule;
jcc3d4e14a2015-04-21 11:32:05 +080033import org.onosproject.net.flow.FlowRuleExtPayLoad;
Carmelo Cascone41605742017-06-19 15:46:44 +090034import org.onosproject.net.flow.IndexTableId;
35import org.onosproject.net.flow.TableId;
Brian O'Connorabafb502014-12-02 22:26:20 -080036import org.onosproject.net.flow.TrafficSelector;
37import org.onosproject.net.flow.TrafficTreatment;
38import org.onosproject.net.flow.criteria.Criterion;
39import org.onosproject.net.flow.criteria.Criterion.Type;
40import org.onosproject.net.flow.instructions.Instruction;
alshabib346b5b32015-03-06 00:42:16 -080041import org.onosproject.net.flow.instructions.Instructions;
Saurav Das86af8f12015-05-25 23:55:33 -070042import org.onosproject.net.flow.instructions.Instructions.MetadataInstruction;
Luca Pretede10c782017-01-05 17:23:08 -080043import org.onosproject.net.provider.ProviderId;
Brian O'Connorabafb502014-12-02 22:26:20 -080044import org.onosproject.net.topology.DefaultTopologyEdge;
45import org.onosproject.net.topology.DefaultTopologyVertex;
Andrey Komarov2398d962016-09-26 15:11:23 +030046import org.onosproject.net.topology.LinkWeigher;
Thomas Vachuska48e64e42015-09-22 15:32:55 -070047import org.onosproject.net.topology.PathServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080048import org.onosproject.net.topology.TopologyVertex;
Ray Milkey5a7787a2015-02-23 11:44:30 -080049import org.onosproject.store.Timestamp;
Ray Milkeye6684082014-10-16 16:59:47 -070050
Luca Pretede10c782017-01-05 17:23:08 -080051import java.util.ArrayList;
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -070052import java.util.Arrays;
53import java.util.Collection;
54import java.util.Collections;
55import java.util.HashSet;
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -070056import java.util.List;
57import java.util.Objects;
58import java.util.Set;
59import java.util.concurrent.atomic.AtomicLong;
60
Thomas Vachuska48e64e42015-09-22 15:32:55 -070061import static org.onosproject.net.NetTestTools.*;
Ray Milkey43a28222015-02-23 13:57:58 -080062
Ray Milkeye6684082014-10-16 16:59:47 -070063/**
64 * Common mocks used by the intent framework tests.
65 */
66public class IntentTestsMocks {
67 /**
68 * Mock traffic selector class used for satisfying API requirements.
69 */
70 public static class MockSelector implements TrafficSelector {
71 @Override
72 public Set<Criterion> criteria() {
73 return new HashSet<>();
74 }
Jonathan Hart936c49d2014-10-23 16:38:59 -070075
76 @Override
77 public Criterion getCriterion(Type type) {
78 return null;
79 }
Ray Milkeye6684082014-10-16 16:59:47 -070080 }
81
82 /**
83 * Mock traffic treatment class used for satisfying API requirements.
84 */
85 public static class MockTreatment implements TrafficTreatment {
86 @Override
alshabib346b5b32015-03-06 00:42:16 -080087 public List<Instruction> deferred() {
Jonathan Hart4a0ba562015-03-23 17:23:33 -070088 return Collections.emptyList();
alshabib346b5b32015-03-06 00:42:16 -080089 }
90
91 @Override
92 public List<Instruction> immediate() {
Jonathan Hart4a0ba562015-03-23 17:23:33 -070093 return Collections.emptyList();
alshabib346b5b32015-03-06 00:42:16 -080094 }
95
96 @Override
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -070097 public List<Instruction> allInstructions() {
Jonathan Hart4a0ba562015-03-23 17:23:33 -070098 return Collections.emptyList();
Jonathan Hart8ef6d3b2015-03-08 21:21:27 -070099 }
100
101 @Override
alshabib346b5b32015-03-06 00:42:16 -0800102 public Instructions.TableTypeTransition tableTransition() {
103 return null;
104 }
105
106 @Override
Jonathan Hart4a0ba562015-03-23 17:23:33 -0700107 public boolean clearedDeferred() {
108 return false;
alshabib346b5b32015-03-06 00:42:16 -0800109 }
Saurav Das86af8f12015-05-25 23:55:33 -0700110
111 @Override
112 public MetadataInstruction writeMetadata() {
113 return null;
114 }
alshabib10c810b2015-08-18 16:59:04 -0700115
116 @Override
Cem Türker3baff672017-10-12 15:09:01 +0300117 public Instructions.StatTriggerInstruction statTrigger() {
118 return null;
119 }
120
121 @Override
alshabib10c810b2015-08-18 16:59:04 -0700122 public Instructions.MeterInstruction metered() {
123 return null;
124 }
cansu.toprak409289d2017-10-27 10:04:05 +0300125
126 @Override
127 public Set<Instructions.MeterInstruction> meters() {
128 return Sets.newHashSet();
129 }
Ray Milkeye6684082014-10-16 16:59:47 -0700130 }
131
132 /**
133 * Mock path service for creating paths within the test.
134 */
Thomas Vachuska48e64e42015-09-22 15:32:55 -0700135 public static class MockPathService extends PathServiceAdapter {
Ray Milkeye6684082014-10-16 16:59:47 -0700136
137 final String[] pathHops;
138 final String[] reversePathHops;
139
140 /**
141 * Constructor that provides a set of hops to mock.
142 *
143 * @param pathHops path hops to mock
144 */
145 public MockPathService(String[] pathHops) {
146 this.pathHops = pathHops;
147 String[] reversed = pathHops.clone();
148 Collections.reverse(Arrays.asList(reversed));
149 reversePathHops = reversed;
150 }
151
152 @Override
153 public Set<Path> getPaths(ElementId src, ElementId dst) {
154 Set<Path> result = new HashSet<>();
155
156 String[] allHops = new String[pathHops.length];
157
158 if (src.toString().endsWith(pathHops[0])) {
159 System.arraycopy(pathHops, 0, allHops, 0, pathHops.length);
160 } else {
161 System.arraycopy(reversePathHops, 0, allHops, 0, pathHops.length);
162 }
163
Thomas Vachuskadc91b552016-03-29 14:02:47 -0700164 result.add(createPath(src instanceof HostId, dst instanceof HostId, allHops));
Ray Milkeye6684082014-10-16 16:59:47 -0700165 return result;
166 }
167
168 @Override
Andrey Komarov2398d962016-09-26 15:11:23 +0300169 public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeigher weigher) {
170 Set<Path> paths = getPaths(src, dst);
Ray Milkey8d3ce432014-11-07 16:21:10 -0800171
172 for (Path path : paths) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300173 DeviceId srcDevice = path.src().elementId() instanceof DeviceId ? path.src().deviceId() : null;
174 DeviceId dstDevice = path.dst().elementId() instanceof DeviceId ? path.dst().deviceId() : null;
Thomas Vachuskadc91b552016-03-29 14:02:47 -0700175 if (srcDevice != null && dstDevice != null) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300176 TopologyVertex srcVertex = new DefaultTopologyVertex(srcDevice);
177 TopologyVertex dstVertex = new DefaultTopologyVertex(dstDevice);
178 Link link = link(src.toString(), 1, dst.toString(), 1);
Ray Milkey8d3ce432014-11-07 16:21:10 -0800179
Andrey Komarov2398d962016-09-26 15:11:23 +0300180 Weight weightValue = weigher.weight(new DefaultTopologyEdge(srcVertex, dstVertex, link));
181 if (weightValue.isNegative()) {
Thomas Vachuskadc91b552016-03-29 14:02:47 -0700182 return new HashSet<>();
183 }
Ray Milkey8d3ce432014-11-07 16:21:10 -0800184 }
185 }
186 return paths;
Ray Milkeye6684082014-10-16 16:59:47 -0700187 }
188 }
Ray Milkey8d3ce432014-11-07 16:21:10 -0800189
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700190 /**
191 * Mock path service for creating paths within the test.
192 *
193 */
Luca Pretede10c782017-01-05 17:23:08 -0800194 public static class Mp2MpMockPathService extends PathServiceAdapter {
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700195
196 final String[] pathHops;
197 final String[] reversePathHops;
198
199 /**
200 * Constructor that provides a set of hops to mock.
201 *
202 * @param pathHops path hops to mock
203 */
204 public Mp2MpMockPathService(String[] pathHops) {
205 this.pathHops = pathHops;
206 String[] reversed = pathHops.clone();
207 Collections.reverse(Arrays.asList(reversed));
208 reversePathHops = reversed;
209 }
210
211 @Override
212 public Set<Path> getPaths(ElementId src, ElementId dst) {
213 Set<Path> result = new HashSet<>();
214
215 String[] allHops = new String[pathHops.length + 2];
216 allHops[0] = src.toString();
217 allHops[allHops.length - 1] = dst.toString();
218
219 if (pathHops.length != 0) {
220 System.arraycopy(pathHops, 0, allHops, 1, pathHops.length);
221 }
222
223 result.add(createPath(allHops));
224
225 return result;
226 }
227
228 @Override
Andrey Komarov2398d962016-09-26 15:11:23 +0300229 public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeigher weigher) {
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700230 final Set<Path> paths = getPaths(src, dst);
231
232 for (Path path : paths) {
233 final DeviceId srcDevice = path.src().elementId() instanceof DeviceId ? path.src().deviceId() : null;
234 final DeviceId dstDevice = path.dst().elementId() instanceof DeviceId ? path.dst().deviceId() : null;
235 if (srcDevice != null && dstDevice != null) {
236 final TopologyVertex srcVertex = new DefaultTopologyVertex(srcDevice);
237 final TopologyVertex dstVertex = new DefaultTopologyVertex(dstDevice);
238 final Link link = link(src.toString(), 1, dst.toString(), 1);
239
Andrey Komarov2398d962016-09-26 15:11:23 +0300240 final Weight weightValue = weigher.weight(new DefaultTopologyEdge(srcVertex, dstVertex, link));
241 if (weightValue.isNegative()) {
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700242 return new HashSet<>();
243 }
244 }
245 }
246 return paths;
247 }
248 }
249
Luca Pretede10c782017-01-05 17:23:08 -0800250 /**
251 * Mock path service for creating paths for MP2SP intent tests, returning
252 * pre-determined paths.
253 */
254 public static class FixedMP2MPMockPathService extends PathServiceAdapter {
Sho SHIMIZUb1681bd2016-02-22 12:47:50 -0800255
Luca Pretede10c782017-01-05 17:23:08 -0800256 final String[] pathHops;
Sho SHIMIZUb1681bd2016-02-22 12:47:50 -0800257
Luca Pretede10c782017-01-05 17:23:08 -0800258 public static final String DPID_1 = "of:s1";
259 public static final String DPID_2 = "of:s2";
260 public static final String DPID_3 = "of:s3";
261 public static final String DPID_4 = "of:s4";
Sho SHIMIZUb1681bd2016-02-22 12:47:50 -0800262
Luca Pretede10c782017-01-05 17:23:08 -0800263 /**
264 * Constructor that provides a set of hops to mock.
265 *
266 * @param pathHops path hops to mock
267 */
268 public FixedMP2MPMockPathService(String[] pathHops) {
269 this.pathHops = pathHops;
Ray Milkey8d3ce432014-11-07 16:21:10 -0800270 }
271
HIGUCHI Yutaca9cc8e2015-10-29 23:26:51 -0700272 @Override
Luca Pretede10c782017-01-05 17:23:08 -0800273 public Set<Path> getPaths(ElementId src, ElementId dst) {
274 List<Link> links = new ArrayList<>();
275 Set<Path> result = new HashSet<>();
276 ProviderId providerId = new ProviderId("of", "foo");
277 DefaultPath path;
278 if (src.toString().equals(DPID_1) && dst.toString().equals(DPID_4)) {
279 links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 1));
280 links.add(NetTestTools.linkNoPrefixes(pathHops[0], 2, dst.toString(), 1));
281 } else if (src.toString().equals(DPID_2) && dst.toString().equals(DPID_4)) {
282 links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 3));
283 links.add(NetTestTools.linkNoPrefixes(pathHops[0], 2, dst.toString(), 1));
284 } else if (src.toString().equals(DPID_4) && dst.toString().equals(DPID_1)) {
285 links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 1));
286 links.add(NetTestTools.linkNoPrefixes(pathHops[0], 2, dst.toString(), 1));
287 } else if (src.toString().equals(DPID_4) && dst.toString().equals(DPID_2)) {
288 links.add(NetTestTools.linkNoPrefixes(src.toString(), 2, pathHops[0], 1));
289 links.add(NetTestTools.linkNoPrefixes(pathHops[0], 3, dst.toString(), 1));
290 } else {
291 return result;
Ray Milkey8d3ce432014-11-07 16:21:10 -0800292 }
Luca Pretede10c782017-01-05 17:23:08 -0800293 path = new DefaultPath(providerId, links, 3);
294 result.add(path);
Ray Milkey8d3ce432014-11-07 16:21:10 -0800295
Luca Pretede10c782017-01-05 17:23:08 -0800296 return result;
Ray Milkey8d3ce432014-11-07 16:21:10 -0800297 }
298
299 @Override
Luca Pretede10c782017-01-05 17:23:08 -0800300 public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeigher weigher) {
301 final Set<Path> paths = getPaths(src, dst);
Ray Milkey8d3ce432014-11-07 16:21:10 -0800302
Luca Pretede10c782017-01-05 17:23:08 -0800303 for (Path path : paths) {
304 final DeviceId srcDevice = path.src().elementId() instanceof DeviceId ? path.src().deviceId() : null;
305 final DeviceId dstDevice = path.dst().elementId() instanceof DeviceId ? path.dst().deviceId() : null;
306 if (srcDevice != null && dstDevice != null) {
307 final TopologyVertex srcVertex = new DefaultTopologyVertex(srcDevice);
308 final TopologyVertex dstVertex = new DefaultTopologyVertex(dstDevice);
309 final Link link = link(src.toString(), 1, dst.toString(), 1);
310
311 final Weight weightValue = weigher.weight(new DefaultTopologyEdge(srcVertex, dstVertex, link));
312 if (weightValue.isNegative()) {
313 return new HashSet<>();
314 }
315 }
316 }
317 return paths;
Ray Milkeye97ede92014-11-20 10:43:12 -0800318 }
Ray Milkey8d3ce432014-11-07 16:21:10 -0800319 }
320
Ray Milkey930fc662014-11-11 16:07:45 -0800321 private static final IntentTestsMocks.MockSelector SELECTOR =
322 new IntentTestsMocks.MockSelector();
323 private static final IntentTestsMocks.MockTreatment TREATMENT =
324 new IntentTestsMocks.MockTreatment();
325
326 public static class MockFlowRule implements FlowRule {
Ray Milkey77a455f2015-03-27 10:08:17 -0700327 static int nextId = 0;
Ray Milkey930fc662014-11-11 16:07:45 -0800328
329 int priority;
Carmelo Cascone41605742017-06-19 15:46:44 +0900330 IndexTableId tableId;
Ray Milkey77a455f2015-03-27 10:08:17 -0700331 long timestamp;
332 int id;
jcc3d4e14a2015-04-21 11:32:05 +0800333 FlowRuleExtPayLoad payLoad;
sangho11c30ac2015-01-22 14:30:55 -0800334
Ray Milkey930fc662014-11-11 16:07:45 -0800335 public MockFlowRule(int priority) {
336 this.priority = priority;
Carmelo Cascone41605742017-06-19 15:46:44 +0900337 this.tableId = DEFAULT_TABLE;
Ray Milkey77a455f2015-03-27 10:08:17 -0700338 this.timestamp = System.currentTimeMillis();
339 this.id = nextId++;
jcc3d4e14a2015-04-21 11:32:05 +0800340 this.payLoad = null;
341 }
342
343 public MockFlowRule(int priority, FlowRuleExtPayLoad payLoad) {
344 this.priority = priority;
345 this.timestamp = System.currentTimeMillis();
346 this.id = nextId++;
347 this.payLoad = payLoad;
Ray Milkey930fc662014-11-11 16:07:45 -0800348 }
349
350 @Override
351 public FlowId id() {
Ray Milkey77a455f2015-03-27 10:08:17 -0700352 return FlowId.valueOf(id);
Ray Milkey930fc662014-11-11 16:07:45 -0800353 }
354
355 @Override
356 public short appId() {
357 return 0;
358 }
359
360 @Override
Sho SHIMIZU75a5bd92014-11-25 11:22:56 -0800361 public GroupId groupId() {
Yi Tsengfa394de2017-02-01 11:26:40 -0800362 return new GroupId(0);
alshabib28204e52014-11-12 18:29:45 -0800363 }
364
365 @Override
Ray Milkey930fc662014-11-11 16:07:45 -0800366 public int priority() {
367 return priority;
368 }
369
370 @Override
371 public DeviceId deviceId() {
372 return did("1");
373 }
374
375 @Override
376 public TrafficSelector selector() {
377 return SELECTOR;
378 }
379
380 @Override
381 public TrafficTreatment treatment() {
382 return TREATMENT;
383 }
384
385 @Override
386 public int timeout() {
387 return 0;
388 }
389
390 @Override
Murat Parlakisikc6759e82016-06-29 03:22:22 -0700391 public int hardTimeout() {
392 return 0;
393 }
394
395 @Override
396 public FlowRemoveReason reason() {
397 return FlowRemoveReason.NO_REASON;
398 }
399
400 @Override
Ray Milkey930fc662014-11-11 16:07:45 -0800401 public boolean isPermanent() {
402 return false;
403 }
404
Brian O'Connor427a1762014-11-19 18:40:32 -0800405 @Override
406 public int hashCode() {
HIGUCHI Yutaca9cc8e2015-10-29 23:26:51 -0700407 return priority;
Brian O'Connor427a1762014-11-19 18:40:32 -0800408 }
Ray Milkey930fc662014-11-11 16:07:45 -0800409
Brian O'Connor427a1762014-11-19 18:40:32 -0800410 @Override
411 public boolean equals(Object obj) {
412 if (this == obj) {
413 return true;
414 }
415 if (obj == null || getClass() != obj.getClass()) {
416 return false;
417 }
418 final MockFlowRule other = (MockFlowRule) obj;
Ray Milkey77a455f2015-03-27 10:08:17 -0700419 return Objects.equals(this.timestamp, other.timestamp) &&
Nikhil Cheerla2ec191f2015-07-09 12:34:54 -0700420 this.id == other.id;
Brian O'Connor427a1762014-11-19 18:40:32 -0800421 }
sangho11c30ac2015-01-22 14:30:55 -0800422
423 @Override
Jonathan Hartf44e42c2015-08-04 09:58:46 -0700424 public boolean exactMatch(FlowRule rule) {
425 return this.equals(rule);
426 }
427
428 @Override
alshabibdb774072015-04-20 13:13:51 -0700429 public int tableId() {
Carmelo Cascone41605742017-06-19 15:46:44 +0900430 return tableId.id();
431 }
432
433 @Override
434 public TableId table() {
alshabib08d98982015-04-21 16:25:50 -0700435 return tableId;
alshabibdb774072015-04-20 13:13:51 -0700436 }
jcc3d4e14a2015-04-21 11:32:05 +0800437
438 @Override
439 public FlowRuleExtPayLoad payLoad() {
440 return payLoad;
441 }
Ray Milkey930fc662014-11-11 16:07:45 -0800442 }
443
Ray Milkey5a7787a2015-02-23 11:44:30 -0800444 public static class MockIntent extends Intent {
445 private static AtomicLong counter = new AtomicLong(0);
446
447 private final Long number;
448
449 public MockIntent(Long number) {
Ray Milkeyebc5d222015-03-18 15:45:36 -0700450 super(NetTestTools.APP_ID, null, Collections.emptyList(),
Nikhil Cheerla2ec191f2015-07-09 12:34:54 -0700451 Intent.DEFAULT_INTENT_PRIORITY);
Ray Milkey5a7787a2015-02-23 11:44:30 -0800452 this.number = number;
453 }
454
Ray Milkey43a28222015-02-23 13:57:58 -0800455 public MockIntent(Long number, Collection<NetworkResource> resources) {
Ray Milkeyebc5d222015-03-18 15:45:36 -0700456 super(NetTestTools.APP_ID, null, resources, Intent.DEFAULT_INTENT_PRIORITY);
Ray Milkey43a28222015-02-23 13:57:58 -0800457 this.number = number;
458 }
459
Ray Milkey5a7787a2015-02-23 11:44:30 -0800460 public Long number() {
461 return number;
462 }
463
464 public static Long nextId() {
465 return counter.getAndIncrement();
466 }
Ray Milkey43a28222015-02-23 13:57:58 -0800467
468 @Override
469 public String toString() {
470 return MoreObjects.toStringHelper(getClass())
471 .add("id", id())
472 .add("appId", appId())
473 .toString();
474 }
Ray Milkey5a7787a2015-02-23 11:44:30 -0800475 }
476
477 public static class MockTimestamp implements Timestamp {
478 final int value;
479
480 public MockTimestamp(int value) {
481 this.value = value;
482 }
483
484 @Override
485 public int compareTo(Timestamp o) {
486 if (!(o instanceof MockTimestamp)) {
487 return -1;
488 }
489 MockTimestamp that = (MockTimestamp) o;
Jonathan Hart72175c22015-03-24 18:55:58 -0700490 return this.value - that.value;
Ray Milkey5a7787a2015-02-23 11:44:30 -0800491 }
Yuta HIGUCHI4f8a3772017-05-16 20:23:49 -0700492
493 @Override
494 public int hashCode() {
495 return value;
496 }
497
498 @Override
499 public boolean equals(Object obj) {
500 if (obj instanceof MockTimestamp) {
501 return this.compareTo((MockTimestamp) obj) == 0;
502 }
503 return false;
504 }
Ray Milkey5a7787a2015-02-23 11:44:30 -0800505 }
506
Yi Tseng2a81c9d2016-09-14 10:14:24 -0700507 /**
508 * Mocks the device service so that a device appears available in the test.
509 */
510 public static class MockDeviceService extends DeviceServiceAdapter {
511 @Override
512 public boolean isAvailable(DeviceId deviceId) {
513 return true;
514 }
515 }
Ray Milkeye6684082014-10-16 16:59:47 -0700516}