Skip to content

Commit

Permalink
Added failing test that illustrates critical bug where a reaction is …
Browse files Browse the repository at this point in the history
…invoked twice at the same logical time.
  • Loading branch information
edwardalee committed May 23, 2021
1 parent 0a0af59 commit 88c2dc0
Showing 1 changed file with 99 additions and 0 deletions.
99 changes: 99 additions & 0 deletions test/C/src/Alignment.lf
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// This test checks that the downstream reaction is not invoked more
// than once at a logical time.
target C {
logging: LOG,
timeout: 1 sec
}
reactor Source {
output out:int;
state count:int(1);
timer t(0, 100 msec);
reaction(t) -> out {=
SET(out, self->count++);
=}
}
reactor Sieve {
input in:int;
output out:bool;
state primes:int*({= NULL =});
state last_prime:int(0);
reaction(startup) {=
// There are 1229 primes between 1 and 10,000.
self->primes = calloc(1229, sizeof(int));
// Primes 1 and 2 are not on the list.
self->primes[0] = 3;
=}
reaction(in) -> out {=
// Reject inputs that are out of bounds.
if (in->value <= 0 || in->value > 10000) {
warning_print("Sieve: Input value out of range: %d.", in->value);
}
// Primes 1 and 2 are not on the list.
if (in->value == 1 || in->value == 2) {
SET(out, true);
return;
}
// If the input is greater than the last found prime, then
// we have to expand the list of primes before checking to
// see whether this is prime.
int candidate = self->primes[self->last_prime];
while (in->value > self->primes[self->last_prime]) {
// The next prime is always odd, so we can increment by two.
candidate += 2;
bool prime = true;
for (int i = 0; i < self->last_prime; i++) {
if (candidate % self->primes[i] == 0) {
// Candidate is not prime. Break and add 2
prime = false;
break;
}
}
// If the candidate is not divisible by any prime in the list, it is prime.
if (prime) {
self->last_prime++;
self->primes[self->last_prime] = candidate;
info_print("Sieve: Found prime: %d.", candidate);
}
}
// We are now assured that the input is less than or
// equal to the last prime on the list.
// See whether the input is an already found prime.
for (int i = self->last_prime; i >= 0; i--) {
// Search the primes from the end, where they are sparser.
if (self->primes[i] == in->value) {
SET(out, true);
return;
}
}
=}
}

reactor Destination {
input ok:bool;
input in:int;
state last_invoked:tag_t({= NEVER_TAG =});
reaction(ok, in) {=
if (ok->is_present && in->is_present) {
info_print("Destination: Input %d is prime at tag (%lld, %d).",
in->value,
current_tag.time - start_time, current_tag.microstep
);
}
if (compare_tags(current_tag, self->last_invoked) <= 0) {
error_print_and_exit("Invoked at tag (%lld, %d), "
"but previously invoked at tag (%lld, %d).",
current_tag.time - start_time, current_tag.microstep,
self->last_invoked.time - start_time, self->last_invoked.microstep
);
}
self->last_invoked = current_tag;
=}
}
main reactor {
source = new Source();
sieve = new Sieve();
destination = new Destination();
source.out -> sieve.in;
sieve.out -> destination.ok;
source.out -> destination.in;
}

0 comments on commit 88c2dc0

Please sign in to comment.