Skip to content

Commit

Permalink
Added cooling and heating test case for HalfLifeController change (#322)
Browse files Browse the repository at this point in the history
  • Loading branch information
climategadgets committed Aug 7, 2024
1 parent adc5bc6 commit ce29734
Showing 1 changed file with 71 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,20 @@
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Sinks;
import reactor.core.scheduler.Schedulers;
import reactor.test.StepVerifier;
import reactor.tools.agent.ReactorDebugAgent;

import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeoutException;
import java.util.function.Predicate;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;

/**
* Test cases for {@link Thermostat}.
Expand Down Expand Up @@ -183,6 +188,7 @@ private void assertPartial(Signal<ProcessController.Status<CallingStatus>, Void>
assertThat(s.isOK()).isTrue();
assertThat(s.isError()).isFalse();
}

@Test
void setpointChangeEmitsSignal() {

Expand Down Expand Up @@ -223,4 +229,69 @@ void setpointChangeEmitsSignal() {

out.dispose();
}

/**
* Make sure setpoint change causes a trail of adjusted signals according to its half-life - in cooling mode.
*/
@Test
void setpointChangeHalfLifeCooling() throws InterruptedException {
assertThatCode(() -> {
setpointChangeHalfLife(
new Thermostat(Clock.systemUTC(), "ts", new Range<>(10d, 40d), 25.0, -1.0, 0, 0, 0, Duration.ofSeconds(10), 1),
20d,
30d);
})
.doesNotThrowAnyException();
}

/**
* Make sure setpoint change causes a trail of adjusted signals according to its half-life - in heating mode.
*/
@Test
void setpointChangeHalfLifeHeating() throws InterruptedException {
assertThatCode(() -> {
setpointChangeHalfLife(
new Thermostat(Clock.systemUTC(), "ts", new Range<>(10d, 40d), 25.0, 1.0, 0, 0, 0, Duration.ofSeconds(10), 1),
30d,
10d);
})
.doesNotThrowAnyException();
}

private void setpointChangeHalfLife(Thermostat ts, Double changedSetpoint, Double temperature) throws InterruptedException {
var count = 20;
var deltaT = 1;
var offset = 0;
var start = Instant.now();
Sinks.Many<Signal<Double, Void>> sourceSink = Sinks.many().multicast().onBackpressureBuffer();
var source = sourceSink.asFlux();

var changeGate = new CountDownLatch(1);
var stopGate = new CountDownLatch(1);

ts
.compute(source)
.subscribeOn(Schedulers.boundedElastic())
.doOnNext(ignored -> changeGate.countDown())
.doOnComplete(stopGate::countDown)

// The data structure passing the sensitivity controller output here is not yet in place, so let's just watch the logs until it is
.subscribe(s -> logger.info("output: {}", s));

// Prime the controller
sourceSink.tryEmitNext(new Signal<Double, Void>(start, temperature));

changeGate.await();

// Introduce a change increasing the demand
ts.setSetpoint(changedSetpoint);

// Feed the rest
while (offset++ < count) {
sourceSink.tryEmitNext(new Signal<Double, Void>(start.plus(Duration.ofSeconds(offset * deltaT)), temperature));
}

sourceSink.tryEmitComplete();
stopGate.await();
}
}

0 comments on commit ce29734

Please sign in to comment.