/*
* This file is part of the ZoneMinder Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
#include "zm_catch2.h"
#include "zm_config.h"
#include "zm_monitor.h"
#include
namespace {
using Step = Monitor::OndemandStep;
void EnsureConfig() {
if (!config.font_file_location) config.font_file_location = "";
if (!config.event_close_mode) config.event_close_mode = "idle";
}
class WakeMonitor : public Monitor {
public:
void WakeUntil(std::chrono::steady_clock::time_point until) {
linked_wake_until_ =
std::chrono::duration_cast(until.time_since_epoch()).count();
}
};
} // namespace
// An on-demand monitor with LinkedMonitors only noticed the link while it was
// capturing, and it stopped capturing 10 s after the last viewer: every later
// alarm on the linked monitor was missed. It now opens the camera when a link
// alarms, and keeps capturing through the alarm it causes.
TEST_CASE("On-demand capture step", "[Monitor]") {
int link_checks = 0;
auto link = [&link_checks](bool alarmed) {
return [&link_checks, alarmed]() { link_checks++; return alarmed; };
};
SECTION("watched: capture, opening the camera if it is closed") {
REQUIRE(Monitor::DecideOndemand(true, true, true, false, link(false)) == Step::CAPTURE);
REQUIRE(Monitor::DecideOndemand(true, true, false, false, link(false)) == Step::PLAY);
}
SECTION("no image yet: capture one for thumbnails") {
REQUIRE(Monitor::DecideOndemand(false, false, true, false, link(false)) == Step::CAPTURE);
REQUIRE(Monitor::DecideOndemand(false, false, false, false, link(false)) == Step::PLAY);
}
SECTION("unwatched and idle: pause, then stay paused") {
REQUIRE(Monitor::DecideOndemand(false, true, true, false, link(false)) == Step::PAUSE);
REQUIRE(Monitor::DecideOndemand(false, true, false, false, link(false)) == Step::SLEEP);
}
SECTION("unwatched but alarmed or woken: keep capturing") {
REQUIRE(Monitor::DecideOndemand(false, true, true, true, link(false)) == Step::CAPTURE);
}
SECTION("paused and a linked monitor alarms: open the camera") {
REQUIRE(Monitor::DecideOndemand(false, true, false, false, link(true)) == Step::PLAY);
}
SECTION("links are read only while the camera is closed") {
// With the camera open the analysis thread evaluates them.
Monitor::DecideOndemand(false, true, true, false, link(true));
Monitor::DecideOndemand(true, true, true, false, link(true));
Monitor::DecideOndemand(true, true, false, false, link(true));
REQUIRE(link_checks == 0);
}
}
TEST_CASE("A link wake lasts until acted on or timed out", "[Monitor]") {
EnsureConfig();
WakeMonitor monitor;
REQUIRE_FALSE(monitor.LinkedWakePending());
monitor.WakeUntil(std::chrono::steady_clock::now() + Monitor::kLinkedWakeTimeout);
REQUIRE(monitor.LinkedWakePending());
monitor.WakeUntil(std::chrono::steady_clock::now() - std::chrono::seconds(1));
REQUIRE_FALSE(monitor.LinkedWakePending());
}