View Javadoc
1   /*
2    * Copyright (c) 2002-2025, City of Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.portal.service.daemon;
35  
36  import java.util.concurrent.BrokenBarrierException;
37  import java.util.concurrent.TimeoutException;
38  
39  import fr.paris.lutece.portal.service.datastore.DatastoreService;
40  import fr.paris.lutece.portal.service.util.AppLogService;
41  import fr.paris.lutece.test.LuteceTestCase;
42  
43  public class AppDaemonServiceConcurrentTest extends LuteceTestCase
44  {
45      private static final String INTERVAL_VALUE = "10000";
46      private static final String JUNIT_DAEMON = "JUNITAppDaemonServiceConcurrentTest";
47      private static final String JUNIT_OTHERDAEMON = "OTHERJUNITAppDaemonServiceConcurrentTest";
48      private static final String DAEMON_INTERVAL_DSKEY = "core.daemon." + JUNIT_DAEMON + ".interval";
49      private static final String OTHERDAEMON_INTERVAL_DSKEY = "core.daemon." + JUNIT_OTHERDAEMON + ".interval";
50  
51      private DaemonEntry _entry;
52      private DaemonEntry _otherEntry;
53  
54      @Override
55      protected void setUp( ) throws Exception
56      {
57          super.setUp( );
58          log( "Creating daemon " + JUNIT_DAEMON );
59          _entry = new DaemonEntry( );
60          _entry.setId( JUNIT_DAEMON );
61          _entry.setNameKey( JUNIT_DAEMON );
62          _entry.setDescriptionKey( JUNIT_DAEMON );
63          _entry.setClassName( TestDaemon.class.getName( ) );
64          _entry.setPluginName( "core" );
65          // AppDaemonService.registerDaemon will copy this datastore value in the
66          // entry.
67          DatastoreService.setInstanceDataValue( DAEMON_INTERVAL_DSKEY, INTERVAL_VALUE );
68          AppDaemonService.registerDaemon( _entry );
69  
70          log( "Creating daemon " + JUNIT_OTHERDAEMON );
71          _otherEntry = new DaemonEntry( );
72          _otherEntry.setId( JUNIT_OTHERDAEMON );
73          _otherEntry.setNameKey( JUNIT_OTHERDAEMON );
74          _otherEntry.setDescriptionKey( JUNIT_OTHERDAEMON );
75          _otherEntry.setClassName( TestConcurrentDaemon.class.getName( ) );
76          _otherEntry.setPluginName( "core" );
77          // AppDaemonService.registerDaemon will copy this datastore value in the
78          // entry.
79          DatastoreService.setInstanceDataValue( OTHERDAEMON_INTERVAL_DSKEY, INTERVAL_VALUE );
80          AppDaemonService.registerDaemon( _otherEntry );
81      }
82  
83      private void log( String message )
84      {
85          AppLogService.info( "{} : {}", this.getClass( ).getName( ), message );
86      }
87  
88      @Override
89      protected void tearDown( ) throws Exception
90      {
91          DatastoreService.removeInstanceData( DAEMON_INTERVAL_DSKEY );
92          AppDaemonService.unregisterDaemon( JUNIT_DAEMON );
93          DatastoreService.removeInstanceData( OTHERDAEMON_INTERVAL_DSKEY );
94          AppDaemonService.unregisterDaemon( JUNIT_OTHERDAEMON );
95          super.tearDown( );
96      }
97  
98      public void testConcurrentDaemonRun( )
99      {
100         assertTrue( AppDaemonService.getDaemonEntries( ).contains( _entry ) );
101         assertTrue( AppDaemonService.getDaemonEntries( ).contains( _otherEntry ) );
102 
103         AppDaemonService.startDaemon( JUNIT_DAEMON );
104         AppDaemonService.startDaemon( JUNIT_OTHERDAEMON );
105 
106         final TestDaemon./../../../../fr/paris/lutece/portal/service/daemon/TestDaemon.html#TestDaemon">TestDaemon daemon = (TestDaemon) _entry.getDaemon( );
107         ( (TestConcurrentDaemon) _otherEntry.getDaemon( ) ).setOther( daemon );
108 
109         AppDaemonService.signalDaemon( JUNIT_DAEMON );
110         AppDaemonService.signalDaemon( JUNIT_OTHERDAEMON );
111         try
112         {
113             // daemon only passes the "go" barrier if otherDeamon runs
114             daemon.waitForCompletion( );
115         }
116         catch( InterruptedException | BrokenBarrierException | TimeoutException e )
117         {
118             fail( "The timeout indicates that the two daemons could not run simultaneously" );
119         }
120 
121     }
122 }