Commit 1f6d9306 authored by yoogx's avatar yoogx
Browse files

* Add test for GQueue

        For openaadl/ocarina#166
parent 999dd10d
......@@ -224,6 +224,7 @@ AC_OUTPUT([
examples/aadlv2/some-types/Makefile
examples/aadlv2/some-types-stdint/Makefile
examples/aadlv2/sunseeker/Makefile
examples/aadlv2/torture_gqueue/Makefile
tools/Makefile
tools/check-symbols/Makefile
tools/check-symbols/examples/Makefile
......
SUBDIRS = d3.1.3-1 ping rma sunseeker producer-consumer some-types \
some-types-stdint flight-mgmt import monitor lua cpp \
packet-store file-store latency code_coverage
packet-store file-store latency code_coverage torture_gqueue
SAMPLE_DIR = ${shell $(CYGPATH_U) '$(OCARINA_PREFIX)/examples/ocarina/polyorb-hi-c/aadlv2'}
......
C_FILES = $(srcdir)/torture.c
AADL_FILES = $(srcdir)/torture.aadl
SCENARIO_FILES = $(srcdir)/scenario.aadl
include $(srcdir)/../../Makefile.common
EXTRA_DIST = $(AADL_FILES) $(SCENARIO_FILES) $(C_FILES)
CLEANDIRS = rma_impl rma_rtems
# torture.c
## About
This file allows the user to test the functions of the gqueue.
The functions directly tested are listed below :
__po_hi_gqueue_store_out,
__po_hi_gqueue_send_output,
__po_hi_gqueue_get_value,
__po_hi_gqueue_next_value,
__po_hi_gqueue_get_count,
__po_hi_gqueue_wait_for_incoming_event.
The functions directly tested are listed below :
__po_hi_gqueue_store_in.
## Global details
The boolean init is used to initialize the semaphores used in the
test, at the first awakening of the periodic function (first to awaken
between the two tasks).
The boolean first_iteration is used to coordinate the awakening of the
two tasks.
In fact, after the first awakening of the periodic function, we go
through the first five tests. However something is needed to indicate
we switch to the next battery of test. That is the role of the
"number" integer and the first_iteration boolean. When the value of
"number" is of 1, the first 5 tests are conducted (with one message at
each awakening). When the value of "number" switches from 1 to 2, the
periodic test 1 is triggered (two messages).
## Sporadic Test details
Each time messages are sent by the periodic task and received by the
Sporadic Task.
The Per Port 1 is linked to the Spo Port 2.
The Per Port 2 is linked to the Spo Port 1.
From the Sporadic 1 to the Sporadic 5:
- tests are made with only one message sent on a output port to an
event port (each time the periodic task is triggered).
- the tests are following each other.
Test Sporadic 1 :
A message has been sent and therefore, a message should be found on each port.
The get_count function is tested by verifying its value on each port is 1.
Test Sporadic 2 :
The goal is to verify :
- whether the wait_for_incoming_event function shows the events in the
right chronological order (FIFO behavior of the function awaited).
- whether the next_value function dequeues correctly the events stored
on each port.
Secondly, to verify :
- whether the value obtained from the get_value function is correct,
compared to the sent values.
As the first message sent was from Port P1 to Port P2, we at first
verify that the first port indicated by the wait_for_next_event
function is the port P2. Then the value sent and obtained thanks to
the get_value function are compared. Finally we verify that after the
dequeue, the get_count functions shows empty ports. At this point,
both ports are empty.
Test Sporadic 3 :
The goal is to verify whether the get_value function (thanks to
semaphores) waits correctly when the port is empty. The test is done
on an empty port. We verify that, when the lock is released, it is
only because both ports are now full : the Periodic task has been
triggered, releasing the get_value function.
Test Sporadic 4 and 5 :
These tests are used to verify this time the FIFO behavior of the
get_value function. The first lines roles are to establish the
optimal set up for the test (2 values on one port, and 1 value only on
the other). We verify thanks to the following assertion that the
value first obtained on the port with 2 events is not the value just
sent, but the previous one (inferior by 1). assert (reception !=
sent_level ); assert (reception == sent_level - 1); The other port
constitutes a control assay.
## Periodic Test details
This time, two messages are sent on the port P3 towards port P4 of the
periodic task : the task are sending messages to itself.
The goal is to verify:
- whether the send_output (or transport_send) function works correctly.
- whether the FIFO behavior is maintained if two messages are sent in
only one awakening of the task.
The awaited behavior of the store_out function is to crush the value
stored out if no send_output is done, which we have been able to see
in the past. We verify that the duo store_out/send_output works fine
when called one after each other.
Finally we verify whether the two functions are recovered in the right
chronological order (the little value and the incremented one next).
The assertion to verify that is quite complex because only the last
value has been stored thanks to sent_lvl. However, as the
incrementation is of 1 at each awakening, it is easy to recover the
previous value sent thanks to the assertion : reception == sent_lvl -
number + j + 1. The value is then dequeued to get to the following
value.
package scenario
public
with Ocarina_Config;
system rma
properties
Ocarina_Config::Timeout_Property => 4000ms;
Ocarina_Config::Referencial_Files =>
("node_a", "node_a.ref");
Ocarina_Config::AADL_Files =>
("torture.aadl");
Ocarina_Config::Root_System_Name => "torture.impl";
Ocarina_Config::Generator => polyorb_hi_c;
Ocarina_Config::Needed_Property_Sets =>
(Ocarina_Config::Data_Model,
Ocarina_Config::Deployment,
Ocarina_Config::Cheddar_Properties);
Ocarina_Config::AADL_Version => AADLv2;
end rma;
system implementation rma.Impl
end rma.Impl;
end scenario;
package Torture
public
with Data_Model;
with Deployment;
data Int
properties
Data_Model::Data_Representation => Integer;
end Int;
thread Per1
features
P1 : out event data port int;
P2 : out event data port int;
P3 : out event data port int;
P4 : in event data port int { Queue_Size => 42;};
properties
Dispatch_Protocol => Periodic;
Period => 1000 ms;
Compute_Execution_Time => 1 ms .. 2 ms;
Priority => 2;
Source_Language => (C); -- Link to code source
Compute_Entrypoint_Source_Text => "period";
Source_Text => ("torture.c");
end Per1;
thread Spo1
features
P1 : in event data port int { Queue_Size => 42;};
P2 : in event data port int { Queue_Size => 42;};
P3 : out event data port Int;
P4 : in event data port int { Queue_Size => 42;};
properties
Dispatch_Protocol => Sporadic; -- Concurrency configuration
Period => 100 ms;
Compute_Execution_Time => 1 ms .. 2 ms;
Priority => 2;
Source_Language => (C); -- Link to code source
Compute_Entrypoint_Source_Text => "sporad";
Source_Text => "torture.c";
end Spo1;
process Torture_Software
end Torture_Software;
process implementation Torture_Software.impl
subcomponents
Per_thread : thread Per1;
Spo_thread : thread Spo1;
connections
C1 : port Per_thread.P2 -> Spo_thread.P1;
C2 : port Per_thread.P1 -> Spo_thread.P2;
C3 : port Spo_thread.P3 -> Spo_thread.P4;
C4 : port Per_thread.P3 -> Per_thread.P4;
end Torture_Software.impl;
processor CPU
properties
Scheduling_Protocol => (POSIX_1003_HIGHEST_PRIORITY_FIRST_PROTOCOL);
Deployment::Execution_Platform => Native;
end CPU;
system Torture
end Torture;
system implementation Torture.impl
subcomponents
Software : process Torture_Software.impl;
Hardware : processor CPU;
properties
Actual_Processor_Binding => (reference (Hardware)) applies to Software;
end Torture.impl;
end Torture;
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
/* Files generated from AADL model */
#include <request.h>
#include <deployment.h>
#include <po_hi_transport.h>
#include <string.h>
#include <stdbool.h>
#include <po_hi_gqueue.h>
#include <semaphore.h>
/*****************************************************************************/
/* Helper macros to access AADL entities */
#define LOCAL_PORT(THREAD_INSTANCE_NAME, PORT_NAME) THREAD_INSTANCE_NAME ## _local_ ## PORT_NAME
#define REQUEST_PORT(THREAD_INSTANCE_NAME, PORT_NAME) THREAD_INSTANCE_NAME ## _global_ ## PORT_NAME
#define PORT_VARIABLE(THREAD_INSTANCE_NAME, PORT_NAME) vars.REQUEST_PORT(THREAD_INSTANCE_NAME,PORT_NAME).REQUEST_PORT(THREAD_INSTANCE_NAME,PORT_NAME)
#define MACRO_TEST 42
#define MACRO_TEST_SECOND 33
#define MAX_TEST 0
int lvl = MACRO_TEST;
int sent_lvl;
int level = MACRO_TEST_SECOND;
int sent_level;
void test_sporad_1(__po_hi_task_id self);
void test_sporad_2(__po_hi_task_id self);
void test_sporad_3(__po_hi_task_id self);
void test_sporad_4(__po_hi_task_id self);
void test_sporad_5(__po_hi_task_id self);
bool init = true;
bool first_iteration = true;
int number = 0;
int count_p1;
int count_p2;
int count_p4;
__po_hi_local_port_t port_p1 = LOCAL_PORT (spo_thread,p1);
__po_hi_local_port_t port_p2 = LOCAL_PORT (spo_thread,p2);
__po_hi_local_port_t port_p4 = LOCAL_PORT (per_thread,p4);
__po_hi_local_port_t port_p3 = LOCAL_PORT (per_thread,p3);
/*
* Semaphore used to coordinate the period and sporad tasks : At the
* end of the first battery of test (number of message == 1), a
* sem_post is done which liberates a sem_wait. The number of
* messages is increased by one.
*/
sem_t *semaphore;
/*****************************************************************************/
void period(__po_hi_task_id self) {
if (init){
semaphore = sem_open("aadl", O_CREAT|O_EXCL, 0644, 0);
init = false;
}
/* *** Boolean and semaphore launching the following test with
*** "number" iterations *** */
if (first_iteration){
sem_wait(semaphore);
printf("\n**** Starting Tests **** \n");
first_iteration = false;
number++;
}
__po_hi_request_t r1;
__po_hi_request_t r2;
/* *** Initial Test of the different functions *** */
if (number < 2){
/* Message sent on Period Port 1 to Sporad port 2 */
sent_lvl = lvl;
r1.port = REQUEST_PORT (per_thread, p1);
r1.PORT_VARIABLE (per_thread,p1) = lvl;
lvl++;
#if defined (TEST_VERBOSE)
printf("\n Storeout P1 to P2, task id = %d, port id = %d", self, LOCAL_PORT (per_thread, p1));
#endif
__po_hi_gqueue_store_out
(self,
LOCAL_PORT (per_thread, p1),
&r1);
/* Message sent on Period Port 2 to Sporad Port 1 */
sent_level = level;
r2.port = REQUEST_PORT (per_thread, p2);
r2.PORT_VARIABLE (per_thread,p2) = level;
level++;
#if defined (TEST_VERBOSE)
printf("\n Storeout P2 to P1, task id = %d, port id = %d\n",
self, LOCAL_PORT (per_thread, p2));
#endif
__po_hi_gqueue_store_out
(self,
LOCAL_PORT (per_thread, p2),
&r2);
}
/* *** Test of two messages sent on one port *** */
/* Transmission */
count_p4 = __po_hi_gqueue_get_count(self, port_p4);
if ((number == 2)&&(count_p4 == 0)){
printf("\n*** TEST PERIODIC 1 ***\n");
count_p4 = __po_hi_gqueue_get_count(self, port_p4);
assert (count_p4 == 0);
for (int i = 1; i <= number; i++){
sent_lvl = lvl;
r1.port = REQUEST_PORT (per_thread, p3);
r1.PORT_VARIABLE (per_thread,p3) = lvl;
lvl++;
#if defined (TEST_VERBOSE)
printf("\n Storeout P1 to P2, task id = %d, port id = %d", self, LOCAL_PORT (per_thread, p3));
#endif
__po_hi_gqueue_store_out
(self,
LOCAL_PORT (per_thread, p3),
&r1);
__po_hi_send_output (self,REQUEST_PORT(per_thread, p3));
}
assert (count_p4 == 0);
}
/* Reception */
count_p4 = __po_hi_gqueue_get_count(self, port_p4);
if ((number == 2)&&(count_p4 == number)){
__po_hi_request_t request;
int reception;
count_p4 = __po_hi_gqueue_get_count(self, port_p4);
for (int j = 0; j < count_p4; j++) {
__po_hi_gqueue_get_value(self,port_p4,&(request));
reception = request.PORT_VARIABLE(per_thread,p4);
#if defined (TEST_VERBOSE)
printf("\nfirst request = %d", MACRO_TEST);
printf("\nsent_lvl = %d", sent_lvl);
printf("\nreceived = %d", reception);
printf("\nnumber, j = %d %d\n", number, j);
#endif
assert(reception == sent_lvl - number + j + 1);
__po_hi_gqueue_next_value (self,port_p4);
}
printf ("Two Messages test passed\n");
first_iteration = true;
sem_post(semaphore);
}
/* ****Test of awaited behavior of a sporadic task**** */
if (number > 2){
int a = 42;
r1.port = REQUEST_PORT (per_thread, p1);
r1.PORT_VARIABLE (per_thread,p1) = a;
__po_hi_gqueue_store_out
(self,
LOCAL_PORT (per_thread, p1),
&r1);
__po_hi_send_output (self,REQUEST_PORT(per_thread, p1));
a++;
}
}
/*****************************************************************************/
void sporad(__po_hi_task_id self) {
/* Test with one message sent by the Period task */
if (number == 1){
/* Test of the get_count function */
test_sporad_1 (self);
/* Test of the next_value function */
test_sporad_2 (self);
/* Test of the function get_value on an empty port */
test_sporad_3 (self);
/* FIFO test on reception port P1 */
test_sporad_4 (self);
/* FIFO test on reception port P2 */
test_sporad_5 (self);
}
/* Test to observe the awaited behavior of a sporadic task */
if (number > 2){
exit(0);
}
/* Boolean and semaphore launching the next type of test */
first_iteration = true;
sem_post(semaphore);
}
/*****************************************************************************/
void test_sporad_1(__po_hi_task_id self) {
printf ("\n*** TEST SPORADIC 1 ***\n");
/*After reception the size used must be 1 */
count_p1 = __po_hi_gqueue_get_count(self, port_p1);
count_p2 = __po_hi_gqueue_get_count(self, port_p2);
assert (count_p1 == 1);
assert (count_p2 == 1);
printf ("get_count test passed\n");
}
/*****************************************************************************/
void test_sporad_2(__po_hi_task_id self) {
int reception;
__po_hi_request_t request;
__po_hi_local_port_t tryport;
printf ("\n*** TEST SPORADIC 2 ***\n");
count_p1 = __po_hi_gqueue_get_count(self, port_p1);
count_p2 = __po_hi_gqueue_get_count(self, port_p2);
assert (count_p1 == 1);
assert (count_p2 == 1);
/* All values are dequeued */
for (int i = 0; i < count_p1 + count_p2 ; i++) {
__po_hi_gqueue_wait_for_incoming_event(self, &tryport);
if (i == 0){
/* The sending is done first on port p1 to port p1 */
assert(tryport == port_p2);
printf ("wait_for_incoming_event test passed \n");
}
__po_hi_gqueue_get_value(self,tryport,&(request));
if (tryport == port_p1){
reception = request.PORT_VARIABLE(spo_thread,p1);
assert (reception == sent_level);
printf ("get_value first test passed \n");
}
if (tryport == port_p2){
reception = request.PORT_VARIABLE(spo_thread,p2);
assert (reception == sent_lvl);
printf ("get_value first test passed \n");
}
__po_hi_gqueue_next_value (self, tryport);
}
/* The ports are supposedly all empty */
count_p1 = __po_hi_gqueue_get_count(self, port_p1);
count_p2 = __po_hi_gqueue_get_count(self, port_p2);
assert (count_p1 == 0);
assert (count_p2 == 0);
printf ("next_value test passed\n");
}
/*****************************************************************************/
void test_sporad_3(__po_hi_task_id self) {
printf ("\n*** TEST SPORADIC 3 ***\n");
__po_hi_request_t request;
/* Test of Get_value on an empty port: */
/* The function supposedly blocks the thread until something is received: */
__po_hi_gqueue_get_value(self,port_p2,&(request));
/* Values have been received on each port*/
count_p1 = __po_hi_gqueue_get_count(self, port_p1);
count_p2 = __po_hi_gqueue_get_count(self, port_p2);
assert (count_p1 == 1);
assert (count_p2 == 1);
printf ("get_value second test passed \n");
}
/*****************************************************************************/
void test_sporad_4(__po_hi_task_id self) {
int reception;
__po_hi_request_t request;
printf ("\n*** TEST SPORADIC 4 ***\n");
count_p1 = __po_hi_gqueue_get_count(self, port_p1);
count_p2 = __po_hi_gqueue_get_count(self, port_p2);
assert (count_p1 == 1);
assert (count_p2 == 1);
/* Dequeuing port P2 */
__po_hi_gqueue_get_value(self,port_p2,&(request));
__po_hi_gqueue_next_value (self, port_p2);
count_p1 = __po_hi_gqueue_get_count(self, port_p1);
count_p2 = __po_hi_gqueue_get_count(self, port_p2);
assert (count_p1 == 1);
assert (count_p2 == 0);
/* Blocking on port P2 */
__po_hi_gqueue_get_value(self,port_p2,&(request));
/* Reception */
count_p1 = __po_hi_gqueue_get_count(self, port_p1);
count_p2 = __po_hi_gqueue_get_count(self, port_p2);
assert (count_p1 == 2);
assert (count_p2 == 1);
/* We have attained optimal configuration */
/* No issue on port P2 */
__po_hi_gqueue_get_value(self,port_p2,&(request));
reception = request.PORT_VARIABLE(spo_thread,p2);
#if defined (TEST_VERBOSE)
printf("\nfirst request = %d", MACRO_TEST);
printf("\nsent_lvl = %d", sent_lvl);
printf("\nreceived = %d", reception);
#endif
assert (reception == sent_lvl);
/* On port P1 : Due to the FIFO aspect of the gqueue, the value
received is not the one just sent, but the previous one */
__po_hi_gqueue_get_value(self,port_p1,&(request));
reception = request.PORT_VARIABLE(spo_thread,p1);
#if defined (TEST_VERBOSE)
printf("\nfirst request = %d", MACRO_TEST_SECOND);
printf("\nsent_level = %d", sent_level);
printf("\nreceived = %d", reception);
#endif
assert (reception != sent_level );
assert (reception == sent_level - 1);
/* We ensure to have only one value on each port */
__po_hi_gqueue_next_value (self,port_p1);
count_p1 = __po_hi_gqueue_get_count(self, port_p1);
count_p2 = __po_hi_gqueue_get_count(self, port_p2);
assert (count_p1 == 1);
assert (count_p2 == 1);
printf ("FIFO test on port p1 passed \n");
}
/*****************************************************************************/
void test_sporad_5(__po_hi_task_id self) {
int reception;
__po_hi_request_t request;
printf ("\n*** TEST SPORADIC 5 ****\n");
count_p1 = __po_hi_gqueue_get_count(self, port_p1);
count_p2 = __po_hi_gqueue_get_count(self, port_p2);
assert (count_p1 == 1);
assert (count_p2 == 1);
/* Dequeuing port P1 */
__po_hi_gqueue_get_value(self,port_p1,&(request));
__po_hi_gqueue_next_value (self, port_p1);
count_p1 = __po_hi_gqueue_get_count(self, port_p1);
count_p2 = __po_hi_gqueue_get_count(self, port_p2);
assert (count_p1 == 0);
assert (count_p2 == 1);
/* Blocking on port P1 */
__po_hi_gqueue_get_value(self,port_p1,&(request));
count_p1 = __po_hi_gqueue_get_count(self, port_p1);
count_p2 = __po_hi_gqueue_get_count(self, port_p2);
assert (count_p1 == 1);
assert (count_p2 == 2);
/* On port p2 : Due to the FIFO aspect of the gqueue, the value
received is not the one just sent, but the previous one */
__po_hi_gqueue_get_value(self,port_p2,&(request));