< prev index next >

bot/src/test/java/org/openjdk/skara/bot/BotRunnerTests.java

Print this page

  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 package org.openjdk.skara.bot;
 24 


 25 import org.junit.jupiter.api.*;
 26 import org.openjdk.skara.host.HostedRepository;
 27 import org.openjdk.skara.json.*;
 28 
 29 import java.nio.file.*;
 30 import java.time.Duration;
 31 import java.util.*;
 32 import java.util.concurrent.TimeoutException;
 33 import java.util.function.Supplier;
 34 import java.util.logging.*;
 35 


 36 class TestWorkItem implements WorkItem {
 37     private final ConcurrencyCheck concurrencyCheck;
 38     private final String description;
 39     boolean hasRun = false;
 40 
 41     interface ConcurrencyCheck {
 42         boolean concurrentWith(WorkItem other);
 43     }
 44 
 45     TestWorkItem(ConcurrencyCheck concurrencyCheck) {
 46         this.concurrencyCheck = concurrencyCheck;
 47         this.description = null;
 48     }
 49 
 50     TestWorkItem(ConcurrencyCheck concurrencyCheck, String description) {
 51         this.concurrencyCheck = concurrencyCheck;
 52         this.description = description;
 53     }
 54 
 55     @Override

 58         System.out.println("Item " + this.toString() + " now running");
 59     }
 60 
 61     @Override
 62     public boolean concurrentWith(WorkItem other) {
 63         return concurrencyCheck.concurrentWith(other);
 64     }
 65 
 66     @Override
 67     public String toString() {
 68         return description != null ? description : super.toString();
 69     }
 70 }
 71 
 72 class TestWorkItemChild extends TestWorkItem {
 73     TestWorkItemChild(ConcurrencyCheck concurrencyCheck, String description) {
 74         super(concurrencyCheck, description);
 75     }
 76 }
 77 
























 78 class TestBot implements Bot {
 79 
 80     private final List<WorkItem> items;
 81     private final Supplier<List<WorkItem>> itemSupplier;
 82 
 83     TestBot(TestWorkItem... items) {
 84         this.items = Arrays.asList(items);
 85         itemSupplier = null;
 86     }
 87 
 88     TestBot(Supplier<List<WorkItem>> itemSupplier) {
 89         items = null;
 90         this.itemSupplier = itemSupplier;
 91     }
 92 
 93     @Override
 94     public List<WorkItem> getPeriodicItems() {
 95         if (items != null) {
 96             return items;
 97         } else {
 98             return itemSupplier.get();
 99         }
100     }
101 }
102 
103 class BotRunnerTests {

105     @BeforeAll
106     static void setUp() {
107         Logger log = Logger.getGlobal();
108         log.setLevel(Level.FINER);
109         log = Logger.getLogger("org.openjdk.bots.cli");
110         log.setLevel(Level.FINER);
111         ConsoleHandler handler = new ConsoleHandler();
112         handler.setLevel(Level.FINER);
113         log.addHandler(handler);
114     }
115 
116     private BotRunnerConfiguration config() {
117         var config = JSON.object();
118         try {
119             return BotRunnerConfiguration.parse(config);
120         } catch (ConfigurationError configurationError) {
121             throw new RuntimeException(configurationError);
122         }
123     }
124 








125     @Test
126     void simpleConcurrent() throws TimeoutException {
127         var item1 = new TestWorkItem(i -> true, "Item 1");
128         var item2 = new TestWorkItem(i -> true, "Item 2");
129         var bot = new TestBot(item1, item2);
130         var runner = new BotRunner(config(), List.of(bot));
131 
132         runner.runOnce(Duration.ofSeconds(10));
133 
134         Assertions.assertTrue(item1.hasRun);
135         Assertions.assertTrue(item2.hasRun);
136     }
137 
138     @Test
139     void simpleSerial() throws TimeoutException {
140         var item1 = new TestWorkItem(i -> false, "Item 1");
141         var item2 = new TestWorkItem(i -> false, "Item 2");
142         var bot = new TestBot(item1, item2);
143         var runner = new BotRunner(config(), List.of(bot));
144 
145         runner.runOnce(Duration.ofSeconds(10));
146 
147         Assertions.assertTrue(item1.hasRun);
148         Assertions.assertTrue(item2.hasRun);
149     }
150 
151     @Test
152     void moreItemsThanScratchPaths() throws TimeoutException {
153         List<TestWorkItem> items = new LinkedList<>();
154         for (int i = 0; i < 20; ++i) {
155             items.add(new TestWorkItem(x -> true, "Item " + i));
156         }
157         var bot = new TestBot(items.toArray(new TestWorkItem[0]));
158         var runner = new BotRunner(config(), List.of(bot));
159 
160         runner.runOnce(Duration.ofSeconds(10));
161 
162         for (var item : items) {
163             Assertions.assertTrue(item.hasRun);
164         }
165     }
166 
167     static class ThrowingItemProvider {
168         private final List<WorkItem> items;
169         private int throwCount;
170 
171         ThrowingItemProvider(List<WorkItem> items, int throwCount) {
172             this.items = items;
173             this.throwCount = throwCount;
174         }
175 
176         List<WorkItem> get() {
177             if (throwCount-- > 0) {
178                 throw new RuntimeException("Sorry, can't provide items just yet");
179             } else {
180                 return items;
181             }
182         }
183     }
184 
185     @Test
186     void periodItemsThrow() throws TimeoutException {
187         var item1 = new TestWorkItem(i -> false, "Item 1");
188         var item2 = new TestWorkItem(i -> false, "Item 2");
189         var provider = new ThrowingItemProvider(List.of(item1, item2), 1);
190 
191         var bot = new TestBot(provider::get);
192 
193         new BotRunner(config(), List.of(bot)).runOnce(Duration.ofSeconds(10));
194         Assertions.assertFalse(item1.hasRun);
195         Assertions.assertFalse(item2.hasRun);
196 
197         new BotRunner(config(), List.of(bot)).runOnce(Duration.ofSeconds(10));
198         Assertions.assertTrue(item1.hasRun);
199         Assertions.assertTrue(item2.hasRun);
200     }
201 
202     @Test
203     void discardAdditionalBlockedItems() throws TimeoutException {
204         var item1 = new TestWorkItem(i -> false, "Item 1");
205         var item2 = new TestWorkItem(i -> false, "Item 2");
206         var item3 = new TestWorkItem(i -> false, "Item 3");
207         var item4 = new TestWorkItem(i -> false, "Item 4");
208         var bot = new TestBot(item1, item2, item3, item4);
209         var runner = new BotRunner(config(), List.of(bot));
210 
211         runner.runOnce(Duration.ofSeconds(10));
212 
213         Assertions.assertTrue(item1.hasRun);
214         Assertions.assertFalse(item2.hasRun);
215         Assertions.assertFalse(item3.hasRun);
216         Assertions.assertTrue(item4.hasRun);
217     }
218 
219     @Test
220     void dontDiscardDifferentBlockedItems() throws TimeoutException {
221         var item1 = new TestWorkItem(i -> false, "Item 1");
222         var item2 = new TestWorkItem(i -> false, "Item 2");
223         var item3 = new TestWorkItem(i -> false, "Item 3");
224         var item4 = new TestWorkItem(i -> false, "Item 4");
225         var item5 = new TestWorkItemChild(i -> false, "Item 5");
226         var item6 = new TestWorkItemChild(i -> false, "Item 6");
227         var item7 = new TestWorkItemChild(i -> false, "Item 7");
228         var bot = new TestBot(item1, item2, item3, item4, item5, item6, item7);
229         var runner = new BotRunner(config(), List.of(bot));
230 
231         runner.runOnce(Duration.ofSeconds(10));
232 
233         Assertions.assertTrue(item1.hasRun);
234         Assertions.assertFalse(item2.hasRun);
235         Assertions.assertFalse(item3.hasRun);
236         Assertions.assertTrue(item4.hasRun);
237         Assertions.assertFalse(item5.hasRun);
238         Assertions.assertFalse(item6.hasRun);
239         Assertions.assertTrue(item7.hasRun);
































240     }
241 }

  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 package org.openjdk.skara.bot;
 24 
 25 import org.openjdk.skara.json.JSON;
 26 
 27 import org.junit.jupiter.api.*;


 28 
 29 import java.nio.file.Path;
 30 import java.time.Duration;
 31 import java.util.*;
 32 import java.util.concurrent.*;
 33 import java.util.function.Supplier;
 34 import java.util.logging.*;
 35 
 36 import static org.junit.jupiter.api.Assertions.*;
 37 
 38 class TestWorkItem implements WorkItem {
 39     private final ConcurrencyCheck concurrencyCheck;
 40     private final String description;
 41     boolean hasRun = false;
 42 
 43     interface ConcurrencyCheck {
 44         boolean concurrentWith(WorkItem other);
 45     }
 46 
 47     TestWorkItem(ConcurrencyCheck concurrencyCheck) {
 48         this.concurrencyCheck = concurrencyCheck;
 49         this.description = null;
 50     }
 51 
 52     TestWorkItem(ConcurrencyCheck concurrencyCheck, String description) {
 53         this.concurrencyCheck = concurrencyCheck;
 54         this.description = description;
 55     }
 56 
 57     @Override

 60         System.out.println("Item " + this.toString() + " now running");
 61     }
 62 
 63     @Override
 64     public boolean concurrentWith(WorkItem other) {
 65         return concurrencyCheck.concurrentWith(other);
 66     }
 67 
 68     @Override
 69     public String toString() {
 70         return description != null ? description : super.toString();
 71     }
 72 }
 73 
 74 class TestWorkItemChild extends TestWorkItem {
 75     TestWorkItemChild(ConcurrencyCheck concurrencyCheck, String description) {
 76         super(concurrencyCheck, description);
 77     }
 78 }
 79 
 80 class TestBlockedWorkItem implements WorkItem {
 81     private final CountDownLatch countDownLatch;
 82 
 83     TestBlockedWorkItem(CountDownLatch countDownLatch) {
 84         this.countDownLatch = countDownLatch;
 85     }
 86 
 87     @Override
 88     public boolean concurrentWith(WorkItem other) {
 89         return false;
 90     }
 91 
 92     @Override
 93     public void run(Path scratchPath) {
 94         System.out.println("Starting to wait...");;
 95         try {
 96             countDownLatch.await();
 97         } catch (InterruptedException e) {
 98             throw new RuntimeException(e);
 99         }
100         System.out.println("Done waiting");
101     }
102 }
103 
104 class TestBot implements Bot {
105 
106     private final List<WorkItem> items;
107     private final Supplier<List<WorkItem>> itemSupplier;
108 
109     TestBot(WorkItem... items) {
110         this.items = Arrays.asList(items);
111         itemSupplier = null;
112     }
113 
114     TestBot(Supplier<List<WorkItem>> itemSupplier) {
115         items = null;
116         this.itemSupplier = itemSupplier;
117     }
118 
119     @Override
120     public List<WorkItem> getPeriodicItems() {
121         if (items != null) {
122             return items;
123         } else {
124             return itemSupplier.get();
125         }
126     }
127 }
128 
129 class BotRunnerTests {

131     @BeforeAll
132     static void setUp() {
133         Logger log = Logger.getGlobal();
134         log.setLevel(Level.FINER);
135         log = Logger.getLogger("org.openjdk.bots.cli");
136         log.setLevel(Level.FINER);
137         ConsoleHandler handler = new ConsoleHandler();
138         handler.setLevel(Level.FINER);
139         log.addHandler(handler);
140     }
141 
142     private BotRunnerConfiguration config() {
143         var config = JSON.object();
144         try {
145             return BotRunnerConfiguration.parse(config);
146         } catch (ConfigurationError configurationError) {
147             throw new RuntimeException(configurationError);
148         }
149     }
150 
151     private BotRunnerConfiguration config(String json) {
152         var config = JSON.parse(json).asObject();
153         try {
154             return BotRunnerConfiguration.parse(config);
155         } catch (ConfigurationError configurationError) {
156             throw new RuntimeException(configurationError);
157         }
158     }
159     @Test
160     void simpleConcurrent() throws TimeoutException {
161         var item1 = new TestWorkItem(i -> true, "Item 1");
162         var item2 = new TestWorkItem(i -> true, "Item 2");
163         var bot = new TestBot(item1, item2);
164         var runner = new BotRunner(config(), List.of(bot));
165 
166         runner.runOnce(Duration.ofSeconds(10));
167 
168         assertTrue(item1.hasRun);
169         assertTrue(item2.hasRun);
170     }
171 
172     @Test
173     void simpleSerial() throws TimeoutException {
174         var item1 = new TestWorkItem(i -> false, "Item 1");
175         var item2 = new TestWorkItem(i -> false, "Item 2");
176         var bot = new TestBot(item1, item2);
177         var runner = new BotRunner(config(), List.of(bot));
178 
179         runner.runOnce(Duration.ofSeconds(10));
180 
181         assertTrue(item1.hasRun);
182         assertTrue(item2.hasRun);
183     }
184 
185     @Test
186     void moreItemsThanScratchPaths() throws TimeoutException {
187         List<TestWorkItem> items = new LinkedList<>();
188         for (int i = 0; i < 20; ++i) {
189             items.add(new TestWorkItem(x -> true, "Item " + i));
190         }
191         var bot = new TestBot(items.toArray(new TestWorkItem[0]));
192         var runner = new BotRunner(config(), List.of(bot));
193 
194         runner.runOnce(Duration.ofSeconds(10));
195 
196         for (var item : items) {
197             assertTrue(item.hasRun);
198         }
199     }
200 
201     static class ThrowingItemProvider {
202         private final List<WorkItem> items;
203         private int throwCount;
204 
205         ThrowingItemProvider(List<WorkItem> items, int throwCount) {
206             this.items = items;
207             this.throwCount = throwCount;
208         }
209 
210         List<WorkItem> get() {
211             if (throwCount-- > 0) {
212                 throw new RuntimeException("Sorry, can't provide items just yet");
213             } else {
214                 return items;
215             }
216         }
217     }
218 
219     @Test
220     void periodItemsThrow() throws TimeoutException {
221         var item1 = new TestWorkItem(i -> false, "Item 1");
222         var item2 = new TestWorkItem(i -> false, "Item 2");
223         var provider = new ThrowingItemProvider(List.of(item1, item2), 1);
224 
225         var bot = new TestBot(provider::get);
226 
227         new BotRunner(config(), List.of(bot)).runOnce(Duration.ofSeconds(10));
228         Assertions.assertFalse(item1.hasRun);
229         Assertions.assertFalse(item2.hasRun);
230 
231         new BotRunner(config(), List.of(bot)).runOnce(Duration.ofSeconds(10));
232         assertTrue(item1.hasRun);
233         assertTrue(item2.hasRun);
234     }
235 
236     @Test
237     void discardAdditionalBlockedItems() throws TimeoutException {
238         var item1 = new TestWorkItem(i -> false, "Item 1");
239         var item2 = new TestWorkItem(i -> false, "Item 2");
240         var item3 = new TestWorkItem(i -> false, "Item 3");
241         var item4 = new TestWorkItem(i -> false, "Item 4");
242         var bot = new TestBot(item1, item2, item3, item4);
243         var runner = new BotRunner(config(), List.of(bot));
244 
245         runner.runOnce(Duration.ofSeconds(10));
246 
247         assertTrue(item1.hasRun);
248         Assertions.assertFalse(item2.hasRun);
249         Assertions.assertFalse(item3.hasRun);
250         assertTrue(item4.hasRun);
251     }
252 
253     @Test
254     void dontDiscardDifferentBlockedItems() throws TimeoutException {
255         var item1 = new TestWorkItem(i -> false, "Item 1");
256         var item2 = new TestWorkItem(i -> false, "Item 2");
257         var item3 = new TestWorkItem(i -> false, "Item 3");
258         var item4 = new TestWorkItem(i -> false, "Item 4");
259         var item5 = new TestWorkItemChild(i -> false, "Item 5");
260         var item6 = new TestWorkItemChild(i -> false, "Item 6");
261         var item7 = new TestWorkItemChild(i -> false, "Item 7");
262         var bot = new TestBot(item1, item2, item3, item4, item5, item6, item7);
263         var runner = new BotRunner(config(), List.of(bot));
264 
265         runner.runOnce(Duration.ofSeconds(10));
266 
267         assertTrue(item1.hasRun);
268         Assertions.assertFalse(item2.hasRun);
269         Assertions.assertFalse(item3.hasRun);
270         assertTrue(item4.hasRun);
271         Assertions.assertFalse(item5.hasRun);
272         Assertions.assertFalse(item6.hasRun);
273         assertTrue(item7.hasRun);
274     }
275 
276     @Test
277     void watchdogTrigger() throws TimeoutException {
278         var countdownLatch = new CountDownLatch(1);
279         var item = new TestBlockedWorkItem(countdownLatch);
280         var bot = new TestBot(item);
281         var runner = new BotRunner(config("{ \"runner\": { \"watchdog\": \"PT0.01S\" } }"), List.of(bot));
282 
283         var errors = new ArrayList<String>();
284         var log = Logger.getLogger("org.openjdk.skara.bot");
285         log.addHandler(new Handler() {
286             @Override
287             public void publish(LogRecord record) {
288                 if (record.getLevel().equals(Level.SEVERE)) {
289                     errors.add(record.getMessage());
290                 }
291             }
292 
293             @Override
294             public void flush() {
295             }
296 
297             @Override
298             public void close() throws SecurityException {
299             }
300         });
301 
302         assertThrows(TimeoutException.class, () -> runner.runOnce(Duration.ofMillis(100)));
303         assertTrue(errors.size() > 0);
304         assertTrue(errors.size() <= 10);
305         countdownLatch.countDown();
306     }
307 }
< prev index next >