View Javadoc
1   package org.apachi.onami.lifecycle.warmup;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import static org.junit.Assert.assertEquals;
23  import static org.junit.Assert.assertFalse;
24  import static org.junit.Assert.assertTrue;
25  
26  import java.util.HashSet;
27  import java.util.Set;
28  import java.util.concurrent.CountDownLatch;
29  import java.util.concurrent.TimeUnit;
30  import java.util.concurrent.TimeoutException;
31  import java.util.concurrent.atomic.AtomicInteger;
32  
33  import org.apache.onami.lifecycle.core.LifeCycleStageModule;
34  import org.apache.onami.lifecycle.core.StageHandler;
35  import org.apache.onami.lifecycle.core.Stager;
36  import org.apache.onami.lifecycle.warmup.WarmUp;
37  import org.apache.onami.lifecycle.warmup.WarmUpModule;
38  import org.apache.onami.lifecycle.warmup.WarmUper;
39  import org.junit.Test;
40  
41  import com.google.inject.AbstractModule;
42  import com.google.inject.Guice;
43  import com.google.inject.Injector;
44  import com.google.inject.Module;
45  
46  public class TestWarmUpManager
47  {
48  
49      @SuppressWarnings( "ThrowableResultOfMethodCallIgnored" )
50      @Test
51      public void testErrors()
52          throws Exception
53      {
54          AbstractModule module = new AbstractModule()
55          {
56              @Override
57              protected void configure()
58              {
59                  bind( WarmUpWithException.class ).asEagerSingleton();
60              }
61          };
62          Injector injector = Guice.createInjector( new WarmUpModule(), module );
63  
64          final AtomicInteger errorCount = new AtomicInteger( 0 );
65          StageHandler stageHandler = new StageHandler()
66          {
67              @Override
68              public <I> void onSuccess( I injectee )
69              {
70              }
71  
72              @Override
73              public <I, E extends Throwable> void onError( I injectee, E error )
74              {
75                  errorCount.incrementAndGet();
76              }
77          };
78          injector.getInstance( LifeCycleStageModule.key( WarmUp.class ) ).stage( stageHandler );
79          assertEquals( 1, errorCount.get() );
80      }
81  
82      @Test
83      public void testDag1()
84          throws Exception
85      {
86          Module module = new AbstractModule()
87          {
88              @Override
89              protected void configure()
90              {
91                  bind( CountDownLatch.class ).toInstance( new CountDownLatch( 3 ) );
92              }
93          };
94          Injector injector = Guice.createInjector( new WarmUpModule(), module );
95          injector.getInstance( Dag1.A.class );
96          injector.getInstance( LifeCycleStageModule.key( WarmUp.class ) ).stage();
97          Recorder recorder = injector.getInstance( Recorder.class );
98  
99          System.out.println( recorder.getRecordings() );
100         System.out.println( recorder.getConcurrents() );
101 
102         assertSingleExecution( recorder );
103         assertNotConcurrent( recorder, "A", "B" );
104         assertNotConcurrent( recorder, "A", "C" );
105 
106         assertEquals( 0, recorder.getInterruptions().size() );
107         assertOrdering( recorder, "A", "B" );
108         assertOrdering( recorder, "A", "C" );
109     }
110 
111     @Test
112     public void testDag2()
113         throws Exception
114     {
115         Injector injector = Guice.createInjector( new WarmUpModule() );
116         injector.getInstance( Dag2.A1.class );
117         injector.getInstance( Dag2.A2.class );
118         injector.getInstance( Dag2.A3.class );
119         injector.getInstance( LifeCycleStageModule.key( WarmUp.class ) ).stage();
120         Recorder recorder = injector.getInstance( Recorder.class );
121 
122         System.out.println( recorder.getRecordings() );
123         System.out.println( recorder.getConcurrents() );
124 
125         assertSingleExecution( recorder );
126 
127         assertNotConcurrent( recorder, "A1", "B1" );
128         assertNotConcurrent( recorder, "A1", "B2" );
129         assertNotConcurrent( recorder, "B1", "C1" );
130         assertNotConcurrent( recorder, "B2", "C1" );
131         assertNotConcurrent( recorder, "A2", "B2" );
132         assertNotConcurrent( recorder, "A2", "B3" );
133         assertNotConcurrent( recorder, "B2", "C2" );
134         assertNotConcurrent( recorder, "B3", "C2" );
135         assertNotConcurrent( recorder, "A3", "B3" );
136         assertNotConcurrent( recorder, "A3", "B4" );
137         assertNotConcurrent( recorder, "B3", "C3" );
138         assertNotConcurrent( recorder, "B4", "C3" );
139 
140         assertEquals( 0, recorder.getInterruptions().size() );
141         assertOrdering( recorder, "A1", "B1" );
142         assertOrdering( recorder, "B1", "C1" );
143         assertOrdering( recorder, "A1", "B2" );
144         assertOrdering( recorder, "B2", "C1" );
145         assertOrdering( recorder, "A2", "B2" );
146         assertOrdering( recorder, "B2", "C2" );
147         assertOrdering( recorder, "A2", "B3" );
148         assertOrdering( recorder, "B3", "C2" );
149         assertOrdering( recorder, "A3", "B3" );
150         assertOrdering( recorder, "B3", "C3" );
151         assertOrdering( recorder, "A3", "B4" );
152         assertOrdering( recorder, "B4", "C3" );
153     }
154 
155     @Test
156     public void testDag3()
157         throws Exception
158     {
159         Injector injector = Guice.createInjector( new WarmUpModule() );
160         injector.getInstance( Dag3.A.class );
161         injector.getInstance( LifeCycleStageModule.key( WarmUp.class ) ).stage();
162         Recorder recorder = injector.getInstance( Recorder.class );
163 
164         System.out.println( recorder.getRecordings() );
165         System.out.println( recorder.getConcurrents() );
166 
167         assertSingleExecution( recorder );
168 
169         assertNotConcurrent( recorder, "C", "D" );
170         assertNotConcurrent( recorder, "B", "D" );
171         assertNotConcurrent( recorder, "A", "B" );
172         assertNotConcurrent( recorder, "A", "C" );
173 
174         assertEquals( 0, recorder.getInterruptions().size() );
175         assertOrdering( recorder, "A", "C" );
176         assertOrdering( recorder, "C", "D" );
177         assertOrdering( recorder, "A", "D" );
178         assertOrdering( recorder, "B", "D" );
179     }
180 
181     @Test
182     public void testDag4()
183         throws Exception
184     {
185         Module module = new AbstractModule()
186         {
187             @Override
188             protected void configure()
189             {
190                 RecorderSleepSettings recorderSleepSettings = new RecorderSleepSettings();
191                 recorderSleepSettings.setBaseSleepFor( "E", 1, TimeUnit.MILLISECONDS );
192                 recorderSleepSettings.setRandomize( false );
193                 bind( RecorderSleepSettings.class ).toInstance( recorderSleepSettings );
194             }
195         };
196         Injector injector = Guice.createInjector( new WarmUpModule(), module );
197         injector.getInstance( Dag4.A.class );
198         injector.getInstance( LifeCycleStageModule.key( WarmUp.class ) ).stage();
199         Recorder recorder = injector.getInstance( Recorder.class );
200 
201         System.out.println( recorder.getRecordings() );
202         System.out.println( recorder.getConcurrents() );
203 
204         assertSingleExecution( recorder );
205         assertEquals( 0, recorder.getInterruptions().size() );
206         assertOrdering( recorder, "D", "E" );
207         assertOrdering( recorder, "C", "E" );
208         assertOrdering( recorder, "B", "D" );
209         assertOrdering( recorder, "A", "B" );
210     }
211 
212     @Test
213     public void testFlat()
214         throws Exception
215     {
216         Injector injector = Guice.createInjector( new WarmUpModule() );
217         Recorder recorder = injector.getInstance( Recorder.class );
218         injector.getInstance( Flat.A.class ).recorder = recorder;
219         injector.getInstance( Flat.B.class ).recorder = recorder;
220         injector.getInstance( LifeCycleStageModule.key( WarmUp.class ) ).stage();
221 
222         System.out.println( recorder.getRecordings() );
223         System.out.println( recorder.getConcurrents() );
224 
225         assertSingleExecution( recorder );
226         assertEquals( 0, recorder.getInterruptions().size() );
227         assertTrue( recorder.getRecordings().indexOf( "A" ) >= 0 );
228         assertTrue( recorder.getRecordings().indexOf( "B" ) >= 0 );
229     }
230 
231     @Test
232     public void testStuck()
233         throws Exception
234     {
235         final CountDownLatch latch = new CountDownLatch( 3 );
236         Module module = new AbstractModule()
237         {
238             @Override
239             protected void configure()
240             {
241                 RecorderSleepSettings recorderSleepSettings = new RecorderSleepSettings();
242                 recorderSleepSettings.setBaseSleepFor( "C", 1, TimeUnit.DAYS );
243                 bind( RecorderSleepSettings.class ).toInstance( recorderSleepSettings );
244                 bind( CountDownLatch.class ).toInstance( latch );
245             }
246         };
247         Injector injector = Guice.createInjector( new TestWarmUpModule(), module );
248         injector.getInstance( Dag1.A.class );
249         Stager<WarmUp> stager = injector.getInstance( LifeCycleStageModule.key( WarmUp.class ) );
250 
251         boolean succeeded;
252         try
253         {
254             stager.stage();
255             succeeded = true;
256         }
257         catch ( RuntimeException e )
258         {
259             succeeded = false;
260             assertTrue( e.getCause() instanceof TimeoutException );
261         }
262 
263         // Wait for all warmup methods to finish after interruption
264         latch.await( 2, TimeUnit.SECONDS );
265 
266         Recorder recorder = injector.getInstance( Recorder.class );
267 
268         System.out.println( recorder.getRecordings() );
269         System.out.println( recorder.getConcurrents() );
270 
271         assertSingleExecution( recorder );
272         assertFalse( succeeded );
273         assertTrue( recorder.getRecordings().toString(), recorder.getRecordings().contains( "C" ) );
274         // What is interrupted depends on warmup order
275         // But C should always be present
276         assertTrue( recorder.getInterruptions().toString(),
277                 recorder.getInterruptions().contains( "C" ) );
278     }
279 
280     private void assertSingleExecution( Recorder recorder )
281     {
282         Set<String> duplicateCheck = new HashSet<String>();
283         for ( String s : recorder.getRecordings() )
284         {
285             assertFalse( s + " ran more than once: " + recorder.getRecordings(), duplicateCheck.contains( s ) );
286             duplicateCheck.add( s );
287         }
288     }
289 
290     private void assertOrdering( Recorder recorder, String base, String dependency )
291     {
292         int baseIndex = recorder.getRecordings().indexOf( base );
293         int dependencyIndex = recorder.getRecordings().indexOf( dependency );
294 
295         assertTrue( baseIndex >= 0 );
296         assertTrue( dependencyIndex >= 0 );
297         assertTrue( "baseIndex: " + baseIndex + " - dependencyIndex: " + dependencyIndex,
298                            baseIndex > dependencyIndex );
299     }
300 
301     private void assertNotConcurrent( Recorder recorder, String task1, String task2 )
302     {
303         for ( Set<String> s : recorder.getConcurrents() )
304         {
305             assertTrue( String.format( "Incorrect concurrency for %s and %s: %s", task1, task2, s ),
306                                !s.contains( task1 ) || !s.contains( task2 ) );
307         }
308     }
309 
310     private static class TestWarmUpModule extends LifeCycleStageModule
311     {
312 
313         @Override
314         protected void configureBindings()
315         {
316             WarmUper<WarmUp> stager = new WarmUper<WarmUp>( WarmUp.class, TimeUnit.SECONDS.toMillis( 1 ) );
317             bindStager( stager ).mappingWith( stager );
318         }
319 
320     }
321 
322 }