LightJason - AgentSpeak(L++)
TestCAgentExecution.java
Go to the documentation of this file.
1 /*
2  * @cond LICENSE
3  * ######################################################################################
4  * # LGPL License #
5  * # #
6  * # This file is part of the LightJason AgentSpeak(L++) #
7  * # Copyright (c) 2015-19, LightJason (info@lightjason.org) #
8  * # This program is free software: you can redistribute it and/or modify #
9  * # it under the terms of the GNU Lesser General Public License as #
10  * # published by the Free Software Foundation, either version 3 of the #
11  * # License, or (at your option) any later version. #
12  * # #
13  * # This program is distributed in the hope that it will be useful, #
14  * # but WITHOUT ANY WARRANTY; without even the implied warranty of #
15  * # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
16  * # GNU Lesser General Public License for more details. #
17  * # #
18  * # You should have received a copy of the GNU Lesser General Public License #
19  * # along with this program. If not, see http://www.gnu.org/licenses/ #
20  * ######################################################################################
21  * @endcond
22  */
23 
24 package org.lightjason.agentspeak.agent;
25 
26 import com.google.common.collect.HashMultimap;
27 import com.google.common.collect.Multimap;
28 import com.google.common.collect.Multimaps;
29 import org.junit.Assume;
30 import org.junit.Before;
31 import org.junit.Test;
43 
44 import javax.annotation.Nonnegative;
45 import javax.annotation.Nonnull;
46 import java.io.FileInputStream;
47 import java.io.InputStream;
48 import java.text.MessageFormat;
49 import java.util.Collections;
50 import java.util.List;
51 import java.util.concurrent.atomic.AtomicBoolean;
52 import java.util.concurrent.atomic.AtomicLong;
53 import java.util.logging.LogManager;
54 import java.util.stream.Collectors;
55 import java.util.stream.LongStream;
56 import java.util.stream.Stream;
57 
58 import static org.junit.Assert.assertTrue;
59 
60 
64 public final class TestCAgentExecution extends IBaseTest
65 {
69  private static final String ASL = "src/test/resources/agent/execution.asl";
73  private IAgent<?> m_agent;
77  private AtomicBoolean m_running;
81  private final Multimap<Long, String> m_log = Multimaps.synchronizedMultimap( HashMultimap.create() );
85  private final Multimap<Long, String> m_result = HashMultimap.create();
86 
87 
88  static
89  {
90  // disable logger
91  LogManager.getLogManager().reset();
92  }
93 
94 
98  @Before
99  public void initialize()
100  {
101  m_running = new AtomicBoolean( true );
102  try
103  (
104  final InputStream l_asl = new FileInputStream( ASL )
105  )
106  {
107  m_agent = new CGenerator( l_asl ).generatesingle();
108  }
109  catch ( final Exception l_exception )
110  {
111  l_exception.printStackTrace();
112  assertTrue( "asl could not be read: {0}", true );
113  }
114 
115 
116  // define execution results
117  m_result.put( 0L, "main" );
118  m_result.put( 1L, "single run" );
119  m_result.put( 1L, "first" );
120  m_result.put( 1L, "second" );
121  m_result.put( 1L, "twovalues equal type" );
122  m_result.put( 1L, "twovalues different type" );
123  m_result.put( 1L, "twovalues with literal" );
124  m_result.put( 2L, "single" );
125  }
126 
132  @Test
133  public final void executionorder() throws Exception
134  {
135  Assume.assumeNotNull( m_agent );
136  Assume.assumeNotNull( m_running );
137 
138 
139  while ( m_running.get() )
140  m_agent.call();
141 
142 
143  // check execution results
144  assertTrue(
145  MessageFormat.format( "number of cycles are incorrect, excpected [{0}] contains [{1}]", m_result.asMap().size(), m_log.asMap().size() ),
146  LongStream.range( 0, m_result.asMap().size() ).allMatch( m_log::containsKey )
147  );
148 
149  assertTrue(
150  MessageFormat.format( "number of log elements during execution are incorrect, expected {0} result {1}", m_result.asMap(), m_log.asMap() ),
151  LongStream.range( 0, m_result.asMap().size() )
152  .allMatch( i -> m_result.get( i ).size() == m_log.asMap().getOrDefault( i, Collections.emptyList() ).size() )
153  );
154 
155  LongStream.range( 0, m_result.asMap().size() ).forEach( i -> assertTrue(
156  MessageFormat.format( "expected result {0} for index {2} is not equal to log {1}", m_result.get( i ), m_log.get( i ), i ),
157  m_result.get( i ).stream().allMatch( j -> m_log.get( i ).contains( j ) )
158  ) );
159 
160  }
161 
162 
166  private final class CGenerator extends IBaseAgentGenerator<CAgent>
167  {
174  CGenerator( final InputStream p_stream ) throws Exception
175  {
176  super(
177  p_stream,
178  Stream.concat(
180  Stream.of(
181  new CStop(),
182  new CLog()
183  )
184  ).collect( Collectors.toSet() )
185  );
186  }
187 
188  @Override
189  public final CAgent generatesingle( final Object... p_data )
190  {
191  return new CAgent( m_configuration );
192  }
193  }
194 
195 
199  private static class CAgent extends IBaseAgent<CAgent>
200  {
204  private static final long serialVersionUID = -7467073439000881088L;
208  private final AtomicLong m_cycle = new AtomicLong();
209 
215  CAgent( final IAgentConfiguration<CAgent> p_configuration )
216  {
217  super( p_configuration );
218  }
219 
220  @Override
221  public final CAgent call() throws Exception
222  {
223  super.call();
224  m_cycle.incrementAndGet();
225  return this;
226  }
227 
233  final long cycle()
234  {
235  return m_cycle.get();
236  }
237  }
238 
239 
243  private final class CStop extends IBaseAction
244  {
248  private static final long serialVersionUID = 5466369414656444520L;
249 
250  @Nonnull
251  @Override
252  public final IPath name()
253  {
254  return CPath.from( "stop" );
255  }
256 
257  @Nonnegative
258  @Override
259  public final int minimalArgumentNumber()
260  {
261  return 0;
262  }
263 
264  @Nonnull
265  @Override
266  public final IFuzzyValue<Boolean> execute( final boolean p_parallel, @Nonnull final IContext p_context,
267  @Nonnull final List<ITerm> p_argument, @Nonnull final List<ITerm> p_return )
268  {
269  m_running.set( false );
270  return CFuzzyValue.from( true );
271  }
272  }
273 
277  private final class CLog extends IBaseAction
278  {
282  private static final long serialVersionUID = 4536335097194230205L;
283 
284  @Nonnull
285  @Override
286  public final IPath name()
287  {
288  return CPath.from( "log" );
289  }
290 
291  @Nonnegative
292  @Override
293  public final int minimalArgumentNumber()
294  {
295  return 1;
296  }
297 
298  @Nonnull
299  @Override
300  public final IFuzzyValue<Boolean> execute( final boolean p_parallel, @Nonnull final IContext p_context,
301  @Nonnull final List<ITerm> p_argument, @Nonnull final List<ITerm> p_return )
302  {
303  m_log.put( p_context.agent().<CAgent>raw().cycle(), p_argument.get( 0 ).<String>raw() );
304  return CFuzzyValue.from( true );
305  }
306  }
307 }
default implementation of an action
final IFuzzyValue< Boolean > execute(final boolean p_parallel, @Nonnull final IContext p_context, @Nonnull final List< ITerm > p_argument, @Nonnull final List< ITerm > p_return)
defines a plan-body operation
base test class with helpers
Definition: IBaseTest.java:33
final Multimap< Long, String > m_log
logs for plan execution
static< N > IFuzzyValue< N > from( @Nonnull final N p_value)
factory
final void executionorder()
execution ordering test
static IPath from( @Nonnull final String p_string)
factor method to build path
Definition: CPath.java:166
class to create a path structure
Definition: CPath.java:53
AtomicBoolean m_running
running flag (agent can disable execution)
execution context with local data
Definition: IContext.java:42
final int minimalArgumentNumber()
minimum number of arguments
static Stream< IAction > actionsFromPackage( @Nullable final String... p_package)
get all classes within an Java package as action
final Multimap< Long, String > m_result
log results
result for an immutable fuzzy value
final IPath name()
returns the name with path of the action
final IPath name()
returns the name with path of the action
final IFuzzyValue< Boolean > execute(final boolean p_parallel, @Nonnull final IContext p_context, @Nonnull final List< ITerm > p_argument, @Nonnull final List< ITerm > p_return)
defines a plan-body operation
final int minimalArgumentNumber()
minimum number of arguments
CAgent(final IAgentConfiguration< CAgent > p_configuration)
ctor
final IAgentConfiguration< T > m_configuration
configuration of an agent