Skip to content

Commit

Permalink
[sre] Add run-time test for SpaceDestroyed event.
Browse files Browse the repository at this point in the history
close #985

Signed-off-by: Stéphane Galland <galland@arakhne.org>
  • Loading branch information
gallandarakhneorg committed Mar 24, 2020
1 parent 10b0cf6 commit ef5d6d5
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 7 deletions.
Expand Up @@ -22,13 +22,15 @@
package io.sarl.sre.tests.framework

import io.sarl.lang.core.Agent
import io.sarl.sre.boot.SreMain
import io.sarl.sre.boot.configs.SreConfig
import io.sarl.sre.services.context.Context
import io.sarl.sre.services.context.ContextService
import io.sarl.sre.services.lifecycle.AgentLife
import io.sarl.sre.services.lifecycle.AgentState
import io.sarl.sre.services.lifecycle.LifecycleService
import io.sarl.sre.test.framework.context.SreRunContext
import java.util.UUID
import io.sarl.sre.services.lifecycle.AgentState
import io.sarl.sre.services.lifecycle.AgentLife

/** Various utilities for helping to set up the tests for the SRE.
* These utilities are specific to the Janus framework.
Expand Down Expand Up @@ -81,4 +83,14 @@ final class SreTestUtilities {
return null
}

/** Replies the SRE configuration.
*
* @param rc the execution context.
* @return the SRE configuration
*/
static def getSreConfig(rc : SreRunContext) : SreConfig {
var kern = (rc.bootstrap as SreMain).getKernel
return kern.configuration
}

}
Expand Up @@ -21,17 +21,26 @@

package io.sarl.sre.tests.runtime.internal

import io.sarl.core.OpenEventSpaceSpecification
import io.sarl.sre.test.framework.context.SreRunContext
import io.sarl.sre.test.framework.^extension.PropertyRestoreExtension
import io.sarl.sre.test.framework.^extension.SreRunExtension
import io.sarl.sre.tests.runtime.internal.mocks.Bye
import io.sarl.sre.tests.runtime.internal.mocks.ByeBye
import io.sarl.sre.tests.runtime.internal.mocks.SpaceDestroyedAgent0
import io.sarl.tests.api.extensions.ContextInitExtension
import io.sarl.tests.api.extensions.JavaVersionCheckExtension
import java.util.UUID
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.RepeatedTest
import org.junit.jupiter.api.Tag
import org.junit.jupiter.api.^extension.ExtendWith

import static org.junit.jupiter.api.Assertions.*
import static io.sarl.sre.test.framework.Constants.*

import static extension io.sarl.sre.tests.framework.SreTestUtilities.*
import static extension io.sarl.tests.api.tools.TestAssertions.*
import static extension org.junit.jupiter.api.Assertions.*

/**
* @author $Author: sgalland$
Expand All @@ -49,10 +58,51 @@ import static org.junit.jupiter.api.Assertions.*
@Tag("run")
class SpaceDestroyedTest {

@RepeatedTest(5)
@DisplayName("run")
@RepeatedTest(10)
@DisplayName("In default context")
@SuppressWarnings("discouraged_reference")
def run(extension rc : SreRunContext) {
fail("To-Do")
var kern = setupTheSreKernel(null, null)

val DELAY = 500

val configuration = rc.getSreConfig
configuration.contexts.spaceDestructionCallbackDelay = DELAY

val spaceId = UUID::randomUUID
val ^space = rootContext.createSpace(typeof(OpenEventSpaceSpecification), spaceId)
^space.assertNotNull

val id0 = UUID::randomUUID
waitForAgentSpawned(id0) [
kern.startAgentWithID(typeof(SpaceDestroyedAgent0), id0, buildAgentInitializationParameters(1))
]

val id1 = UUID::randomUUID
waitForAgentSpawned(id1) [
kern.startAgentWithID(typeof(SpaceDestroyedAgent0), id1, buildAgentInitializationParameters(2, ^space))
]

val id2 = UUID::randomUUID
waitForAgentSpawned(id2) [
kern.startAgentWithID(typeof(SpaceDestroyedAgent0), id2, buildAgentInitializationParameters(3))
]

waitForSpaceDestroyed(spaceId) [
rootContext.defaultSpace.emit(UUID::randomUUID, new Bye)
]

Thread::sleep(DELAY * 4)

rootContext.defaultSpace.emit(UUID::randomUUID, new ByeBye)

waitForTheKernel(STANDARD_TIMEOUT)

allResults.assertContains(
"AG1: space destroyed " + rootContext.ID + " " + spaceId + " in default space",
"AG2: space destroyed " + rootContext.ID + " " + spaceId + " in default space",
"AG3: space destroyed " + rootContext.ID + " " + spaceId + " in default space"
)
}

}
@@ -0,0 +1,90 @@
/*
* $Id$
*
* SARL is an general-purpose agent programming language.
* More details on http://www.sarl.io
*
* Copyright (C) 2014-2020 the original authors or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.sarl.sre.tests.runtime.internal.mocks

import io.sarl.core.Behaviors
import io.sarl.core.DefaultContextInteractions
import io.sarl.core.Initialize
import io.sarl.core.InnerContextAccess
import io.sarl.core.Lifecycle
import io.sarl.core.OpenEventSpace
import io.sarl.core.SpaceDestroyed
import io.sarl.sre.test.framework.skills.TestingCapacity
import io.sarl.sre.test.framework.skills.TestingSkill

/**
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
agent SpaceDestroyedAgent0 {

uses DefaultContextInteractions, InnerContextAccess, Lifecycle, Behaviors

uses TestingCapacity

var number : int

var ^space : OpenEventSpace

on Initialize {
setSkill(new TestingSkill(occurrence))
this.number = occurrence.parameters.get(1) as Integer

this.^space = null
if (occurrence.parameters.size > 2) {
this.^space = occurrence.parameters.get(2) as OpenEventSpace
if (this.^space !== null) {
this.^space.register(asEventListener)
}
}
}

on SpaceDestroyed {
var msg : String
if (occurrence.inInnerDefaultSpace) {
msg = "inner"
} else if (occurrence.inDefaultSpace) {
msg = "default"
} else {
msg = "other"
}
addResult("AG" + this.number + ": space destroyed " + occurrence.source.UUID + " " + occurrence.spaceID.ID + " in " + msg + " space")
if (^space !== null) {
killMe
}
}

on Bye {
if (this.^space !== null) {
this.^space.unregister(asEventListener)
}
}

on ByeBye {
if (this.^space === null) {
killMe
}
}

}
Expand Up @@ -26,6 +26,7 @@ import io.sarl.bootstrap.SREBootstrap
import io.sarl.core.AgentKilled
import io.sarl.core.AgentSpawned
import io.sarl.core.OpenEventSpace
import io.sarl.core.SpaceDestroyed
import io.sarl.lang.annotation.PrivateAPI
import io.sarl.lang.core.Agent
import io.sarl.lang.core.AgentContext
Expand All @@ -51,10 +52,10 @@ import org.eclipse.xtend.lib.annotations.Accessors
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1
import org.opentest4j.AssertionFailedError

import static io.sarl.sre.test.framework.Constants.*
import static org.junit.jupiter.api.Assertions.*

import static extension org.junit.jupiter.api.Assertions.assertEquals
import static io.sarl.sre.test.framework.Constants.*

/**
* Context for running the SRE. This context is thread-safe.
Expand Down Expand Up @@ -573,6 +574,15 @@ class SreRunContext {
typeof(AgentKilled).registerEventHandler(^space, code)
}

/** Register the given code for space destroyed.
*
* @param space the space to listen into. If {@code null}, the default space of the root context is used.
* @param code the code to run on space destroyed.
*/
def onSpaceDestroyed(^space : OpenEventSpace = null, code : (SpaceDestroyed)=>void) {
typeof(SpaceDestroyed).registerEventHandler(^space, code)
}

/** Register a listener on agent spawned that is waiting for a specific agent.
*
* <p>If the {@code code} is provided, this function executes the {@code code}
Expand Down Expand Up @@ -680,4 +690,32 @@ class SreRunContext {
return w
}

/** Register a listener on space destroyed event that is waiting for a specific space destruction.
*
* <p>If the {@code code} is provided, this function executes the {@code code}
* and wait for the destruction event for the space with the given {@code id}.
* If the {@code code} is {@code null}, the returned object should enable to wait for
* the space destroyed event.
*
* @param identifier are the identifier of the space to wait for.
* @param space the space to listen into. If {@code null}, the default space of the root context is used.
* @param timeout the max timeout to apply for waiting.
* @param code the code to run and wait for the space destruction event.
* @return the object that permits to wait for the destruction.
*/
def waitForSpaceDestroyed(identifier : UUID, ^space : OpenEventSpace = null, timeout : int = STANDARD_TIMEOUT, code : ()=>void = null) : Wait {
val lock = new AtomicBoolean
onSpaceDestroyed(^space) [
if (it.spaceID.ID == identifier) {
lock.set(true)
}
]
val w = new BooleanWait(lock, this.directFailureCause)
if (code !== null) {
code.apply()
w.doWait(timeout)
}
return w
}

}

0 comments on commit ef5d6d5

Please sign in to comment.