Skip to content

Commit 3abf209

Browse files
authored
Merge pull request #31 from stephenc/jenkins-42150
[FIXED JENKINS-42150] Add latency options to mock scm impl in SCM API's test artifact
2 parents 96c0746 + a6d46f9 commit 3abf209

File tree

2 files changed

+130
-1
lines changed

2 files changed

+130
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2017 CloudBees, Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*
24+
*/
25+
26+
package jenkins.scm.impl.mock;
27+
28+
import java.util.Random;
29+
import java.util.concurrent.TimeUnit;
30+
31+
/**
32+
* Represents latency in connecting to the {@link MockSCM}.
33+
*
34+
* @since 2.0.5
35+
*/
36+
public abstract class MockLatency {
37+
38+
private static final MockLatency NONE = new MockLatency() {
39+
@Override
40+
public void apply() throws InterruptedException {
41+
}
42+
};
43+
private static final MockLatency YIELD = new MockLatency() {
44+
@Override
45+
public void apply() throws InterruptedException {
46+
Thread.yield();
47+
}
48+
};
49+
50+
public abstract void apply() throws InterruptedException;
51+
52+
/**
53+
* A fixed latency.
54+
* @param time the latency.
55+
* @param units the units.
56+
* @return a fixed latency.
57+
*/
58+
public static MockLatency fixed(final long time, final TimeUnit units) {
59+
return new MockLatency() {
60+
@Override
61+
public void apply() throws InterruptedException {
62+
units.sleep(time);
63+
}
64+
};
65+
}
66+
67+
/**
68+
* A fixed latency for all threads except the current thread.
69+
*
70+
* @param time the latency.
71+
* @param units the units.
72+
* @return a fixed latency.
73+
*/
74+
public static MockLatency fixedForOtherThreads(final long time, final TimeUnit units) {
75+
final Thread safe = Thread.currentThread();
76+
return new MockLatency() {
77+
@Override
78+
public void apply() throws InterruptedException {
79+
if (Thread.currentThread() != safe) {
80+
units.sleep(time);
81+
}
82+
}
83+
};
84+
}
85+
86+
/**
87+
* A random latency that has an expected average time.
88+
*
89+
* @param time the expected average latency.
90+
* @param units the units.
91+
* @return a fixed latency.
92+
*/
93+
public static MockLatency average(final long time, final TimeUnit units) {
94+
return new MockLatency() {
95+
final Random entropy = new Random();
96+
@Override
97+
public void apply() throws InterruptedException {
98+
long ms = units.toMillis(time);
99+
ms = Math.min(ms * 3L, Math.max((long) (ms + (ms * entropy.nextGaussian())), 1L));
100+
Thread.sleep(ms);
101+
}
102+
};
103+
}
104+
/**
105+
* A latency that just forces the thread scheduler to yield.
106+
*
107+
* @return a minimal latency that causes background threads to run.
108+
*/
109+
public static MockLatency yield() {
110+
return YIELD;
111+
}
112+
/**
113+
* A latency that just forces the thread scheduler to yield.
114+
*
115+
* @return a minimal latency that causes background threads to run.
116+
*/
117+
public static MockLatency none() {
118+
return NONE;
119+
}
120+
}

src/test/java/jenkins/scm/impl/mock/MockSCMController.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
package jenkins.scm.impl.mock;
2727

2828
import edu.umd.cs.findbugs.annotations.CheckForNull;
29+
import edu.umd.cs.findbugs.annotations.NonNull;
2930
import hudson.FilePath;
3031
import java.io.ByteArrayInputStream;
3132
import java.io.Closeable;
@@ -58,6 +59,8 @@ public class MockSCMController implements Closeable {
5859

5960
private Map<String, Repository> repositories = new TreeMap<String, Repository>();
6061
private List<MockFailure> faults = new ArrayList<MockFailure>();
62+
@NonNull
63+
private MockLatency latency = MockLatency.none();
6164
private String displayName;
6265
private String description;
6366
private String url;
@@ -80,6 +83,11 @@ public static MockSCMController create() {
8083
return c;
8184
}
8285

86+
public MockSCMController withLatency(@NonNull MockLatency latency) {
87+
this.latency = latency;
88+
return this;
89+
}
90+
8391
/**
8492
* (Re)creates a {@link MockSCMController} for use when you are running a data migration test.
8593
* It will be the callers responsibility to restore the state of the {@link MockSCMController} accordingly.
@@ -178,7 +186,8 @@ public synchronized void clearFaults() {
178186

179187
public synchronized void checkFaults(@CheckForNull String repository, @CheckForNull String branch,
180188
@CheckForNull String revision, boolean actions)
181-
throws IOException {
189+
throws IOException, InterruptedException {
190+
latency.apply();
182191
for (MockFailure fault: faults) {
183192
fault.check(repository, branch, revision, actions);
184193
}

0 commit comments

Comments
 (0)