View | Details | Raw Unified | Return to bug 63490
Collapse All | Expand All

(-)src/core/org/apache/jmeter/threads/JMeterThread.java (+14 lines)
Lines 935-940 Link Here
935
        }
935
        }
936
    }
936
    }
937
937
938
    /**
939
     * Run all configured timers and sleep the total amount of time.
940
     * <p>
941
     * If the amount of time would amount to an ending after endTime, then
942
     * end the current thread by setting {@code running} to {@code false} and
943
     * return immediately.
944
     * 
945
     * @param timers to be used for calculating the delay
946
     */
938
    private void delay(List<Timer> timers) {
947
    private void delay(List<Timer> timers) {
939
        long totalDelay = 0;
948
        long totalDelay = 0;
940
        for (Timer timer : timers) {
949
        for (Timer timer : timers) {
Lines 955-960 Link Here
955
                    // We reduce pause to ensure end of test is not delayed by a sleep ending after test scheduled end
964
                    // We reduce pause to ensure end of test is not delayed by a sleep ending after test scheduled end
956
                    // See Bug 60049
965
                    // See Bug 60049
957
                    totalDelay = TIMER_SERVICE.adjustDelay(totalDelay, endTime);
966
                    totalDelay = TIMER_SERVICE.adjustDelay(totalDelay, endTime);
967
                    if (totalDelay < 0) {
968
                        log.debug("The delay would be longer than the scheduled period, so stop thread now.");
969
                        running = false;
970
                        return;
971
                    }
958
                }
972
                }
959
                TimeUnit.MILLISECONDS.sleep(totalDelay);
973
                TimeUnit.MILLISECONDS.sleep(totalDelay);
960
            } catch (InterruptedException e) {
974
            } catch (InterruptedException e) {
(-)src/core/org/apache/jmeter/timers/TimerService.java (-2 / +2 lines)
Lines 60-72 Link Here
60
     * Adjust delay so that initialDelay does not exceed end of test
60
     * Adjust delay so that initialDelay does not exceed end of test
61
     * @param initialDelay initial delay in millis
61
     * @param initialDelay initial delay in millis
62
     * @param endTime End time of JMeterThread
62
     * @param endTime End time of JMeterThread
63
     * @return initialDelay or adjusted delay
63
     * @return initialDelay or {@code -1} if delay is too long
64
     */
64
     */
65
    public long adjustDelay(final long initialDelay, long endTime) {
65
    public long adjustDelay(final long initialDelay, long endTime) {
66
        if (endTime > 0) {
66
        if (endTime > 0) {
67
            long now = System.currentTimeMillis();
67
            long now = System.currentTimeMillis();
68
            if (initialDelay > endTime - now) {
68
            if (initialDelay > endTime - now) {
69
                return endTime - now;
69
                return -1;
70
            }
70
            }
71
        }
71
        }
72
        return initialDelay;
72
        return initialDelay;
(-)test/src/org/apache/jmeter/threads/TestJMeterThread.java (-1 / +103 lines)
Lines 18-24 Link Here
18
18
19
package org.apache.jmeter.threads;
19
package org.apache.jmeter.threads;
20
20
21
import static org.junit.Assert.assertFalse;
22
import static org.junit.Assert.assertTrue;
23
24
import java.util.Date;
25
26
import org.apache.jmeter.control.LoopController;
27
import org.apache.jmeter.samplers.AbstractSampler;
28
import org.apache.jmeter.samplers.Entry;
29
import org.apache.jmeter.samplers.SampleResult;
21
import org.apache.jmeter.testelement.ThreadListener;
30
import org.apache.jmeter.testelement.ThreadListener;
31
import org.apache.jmeter.timers.ConstantTimer;
22
import org.apache.jorphan.collections.HashTree;
32
import org.apache.jorphan.collections.HashTree;
23
import org.junit.Test;
33
import org.junit.Test;
24
34
Lines 26-31 Link Here
26
 * Tests for {@link JMeterThread}
36
 * Tests for {@link JMeterThread}
27
 */
37
 */
28
public class TestJMeterThread {
38
public class TestJMeterThread {
39
40
    private static final class DummySampler extends AbstractSampler {
41
        private static final long serialVersionUID = 1L;
42
        private boolean called = false;
43
44
        public boolean isCalled() {
45
            return called;
46
        }
47
48
        @Override
49
        public SampleResult sample(Entry e) {
50
            called = true;
51
            return null;
52
        }
53
54
        @Override
55
        public int hashCode() {
56
            final int prime = 31;
57
            int result = super.hashCode();
58
            result = prime * result + (called ? 1231 : 1237);
59
            return result;
60
        }
61
62
        @Override
63
        public boolean equals(Object obj) {
64
            if (this == obj)
65
                return true;
66
            if (!super.equals(obj))
67
                return false;
68
            if (getClass() != obj.getClass())
69
                return false;
70
            DummySampler other = (DummySampler) obj;
71
            return called == other.called;
72
        }
73
74
    }
75
29
    private static class ThrowingThreadListener implements ThreadListener {
76
    private static class ThrowingThreadListener implements ThreadListener {
30
77
31
        private boolean throwError;
78
        private boolean throwError;
Lines 71-75 Link Here
71
                new JMeterThread.ThreadListenerTraverser(true);
118
                new JMeterThread.ThreadListenerTraverser(true);
72
        hashTree.traverse(traverser);
119
        hashTree.traverse(traverser);
73
    }
120
    }
74
    
121
122
    @Test
123
    public void testBug63490EndTestWhenDelayIsTooLongForScheduler() {
124
125
        JMeterContextService.getContext().setVariables(new JMeterVariables());
126
127
        HashTree testTree = new HashTree();
128
        LoopController samplerController = createLoopController();
129
        testTree.add(samplerController);
130
        testTree.add(samplerController, createConstantTimer("3000"));
131
        DummySampler dummySampler = createSampler();
132
        testTree.add(samplerController, dummySampler);
133
134
        TestCompiler compiler = new TestCompiler(testTree);
135
        testTree.traverse(compiler);
136
137
        ThreadGroup threadGroup = new ThreadGroup();
138
        threadGroup.setNumThreads(1);
139
        long maxDuration = 2000l;
140
        threadGroup.setDuration(maxDuration);
141
142
        JMeterThread jMeterThread = new JMeterThread(testTree, threadGroup, null);
143
        jMeterThread.setScheduled(true);
144
        jMeterThread.setEndTime(System.currentTimeMillis() + maxDuration);
145
        jMeterThread.setThreadGroup(threadGroup);
146
        long startTime = new Date().getTime();
147
        jMeterThread.run();
148
        long duration = new Date().getTime() - startTime;
149
150
        assertFalse("Sampler should not be called", dummySampler.isCalled());
151
152
        // the duration of this test plan should currently be around zero seconds,
153
        // but it is allowed to take up to maxDuration amount of time
154
        assertTrue("Test plan should not run for longer than duration", duration <= maxDuration);
155
    }
156
157
    private LoopController createLoopController() {
158
        LoopController result = new LoopController();
159
        result.setLoops(LoopController.INFINITE_LOOP_COUNT);
160
        result.setEnabled(true);
161
        return result;
162
    }
163
164
    private DummySampler createSampler() {
165
        DummySampler result = new DummySampler();
166
        result.setName("Call me");
167
        return result;
168
    }
169
170
    private ConstantTimer createConstantTimer(String delay) {
171
        ConstantTimer constantTimer = new ConstantTimer();
172
        constantTimer.setEnabled(true);
173
        constantTimer.setDelay(delay);
174
        constantTimer.setName("Long delay");
175
        return constantTimer;
176
    }
75
}
177
}
(-)test/src/org/apache/jmeter/timers/TimerServiceTest.java (-2 / +15 lines)
Lines 30-37 Link Here
30
    public void testBigInitialDelay() {
30
    public void testBigInitialDelay() {
31
        long now = System.currentTimeMillis();
31
        long now = System.currentTimeMillis();
32
        long adjustedDelay = sut.adjustDelay(Long.MAX_VALUE, now + 1000L);
32
        long adjustedDelay = sut.adjustDelay(Long.MAX_VALUE, now + 1000L);
33
        // As #adjustDelay uses System#currentTimeMillis we can't be sure, that the value is exact 1000L
33
        Assert.assertThat("TimerService should return -1 as delay would lead to a time after end time",
34
        Assert.assertThat(Math.abs(adjustedDelay - 1000L) < 150L, CoreMatchers.is(true));
34
                Long.valueOf(adjustedDelay), CoreMatchers.is(Long.valueOf(-1)));
35
    }
35
    }
36
36
37
    @Test
38
    public void testSmallInitialDelay() {
39
        long now = System.currentTimeMillis();
40
        Assert.assertThat("TimerService should not change the delay as the end time is far away",
41
                Long.valueOf(sut.adjustDelay(1000L, now + 20000L)), CoreMatchers.is(Long.valueOf(1000L)));
42
    }
43
44
    @Test
45
    public void testNegativeEndTime() {
46
        Assert.assertThat("TimerService should not change the delay as the indicated end time is far away",
47
                Long.valueOf(sut.adjustDelay(1000L, -1)), CoreMatchers.is(Long.valueOf(1000L)));
48
    }
49
37
}
50
}

Return to bug 63490