598 lines
No EOL
17 KiB
C++
598 lines
No EOL
17 KiB
C++
#include <QtTest/QtTest>
|
|
#include "actors/actor.h"
|
|
#include "actors/timeractor.h"
|
|
#include "actors/sensoractor.h"
|
|
#include "actors/scriptactor.h"
|
|
#include "sensors/sensor.h"
|
|
|
|
class TestActor : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
private slots:
|
|
void initTestCase()
|
|
{
|
|
// Setup for all tests
|
|
}
|
|
|
|
void testActorCreation()
|
|
{
|
|
Actor actor;
|
|
|
|
// Actor should be active by default
|
|
QVERIFY(actor.isActive());
|
|
|
|
// Actor should not be exhausted by default
|
|
QVERIFY(!actor.isExausted());
|
|
}
|
|
|
|
void testActorActivation()
|
|
{
|
|
Actor actor;
|
|
|
|
// Test makeActive/makeInactive
|
|
actor.makeActive();
|
|
QVERIFY(actor.isActive());
|
|
|
|
actor.makeInactive();
|
|
QVERIFY(!actor.isActive());
|
|
}
|
|
|
|
void testActorSetActive()
|
|
{
|
|
Actor actor;
|
|
|
|
// Test setActive
|
|
actor.setActive(1);
|
|
QVERIFY(actor.isActive());
|
|
|
|
actor.setActive(0);
|
|
QVERIFY(!actor.isActive());
|
|
}
|
|
|
|
void testActorTriggerValue()
|
|
{
|
|
Actor actor;
|
|
|
|
// Default trigger value should be 0
|
|
QVERIFY(actor.getTriggerValue() == 0);
|
|
|
|
// Set trigger value
|
|
actor.setTriggerValue(1);
|
|
QVERIFY(actor.getTriggerValue() == 1);
|
|
|
|
actor.setTriggerValue(255);
|
|
QVERIFY(actor.getTriggerValue() == 255);
|
|
}
|
|
|
|
void testActorActionName()
|
|
{
|
|
Actor actor;
|
|
|
|
// Default trigger value is 0, so action name should be "off"
|
|
QVERIFY(actor.actionName() == "off");
|
|
|
|
// Set trigger value to 1
|
|
actor.setTriggerValue(1);
|
|
QVERIFY(actor.actionName() == "on");
|
|
|
|
// Set trigger value to something else
|
|
actor.setTriggerValue(5);
|
|
QVERIFY(actor.actionName() == "value to 5");
|
|
}
|
|
|
|
void testActorJsonSerialization()
|
|
{
|
|
Actor actor;
|
|
actor.setTriggerValue(1);
|
|
actor.makeInactive();
|
|
|
|
QJsonObject json;
|
|
actor.store(json);
|
|
|
|
// Verify JSON contents
|
|
QVERIFY(json.contains("Active"));
|
|
QVERIFY(json.contains("Exausted"));
|
|
QVERIFY(json.contains("TriggerValue"));
|
|
|
|
QVERIFY(json["Active"].toBool() == false);
|
|
QVERIFY(json["Exausted"].toBool() == false);
|
|
QVERIFY(json["TriggerValue"].toInt() == 1);
|
|
}
|
|
|
|
void testActorJsonDeserialization()
|
|
{
|
|
QJsonObject json;
|
|
json["Active"] = false;
|
|
json["Exausted"] = true;
|
|
json["TriggerValue"] = 5;
|
|
|
|
Actor actor;
|
|
actor.load(json);
|
|
|
|
QVERIFY(actor.isActive() == false);
|
|
QVERIFY(actor.isExausted() == true);
|
|
QVERIFY(actor.getTriggerValue() == 5);
|
|
}
|
|
|
|
void testActorCreateActor()
|
|
{
|
|
// Test creating different actor types
|
|
std::shared_ptr<Actor> alarmActor = Actor::createActor("Alarm");
|
|
QVERIFY(alarmActor != nullptr);
|
|
|
|
std::shared_ptr<Actor> sensorActor = Actor::createActor("Sensor");
|
|
QVERIFY(sensorActor != nullptr);
|
|
|
|
std::shared_ptr<Actor> timerActor = Actor::createActor("Timer");
|
|
QVERIFY(timerActor != nullptr);
|
|
|
|
std::shared_ptr<Actor> regulatorActor = Actor::createActor("Regulator");
|
|
QVERIFY(regulatorActor != nullptr);
|
|
|
|
std::shared_ptr<Actor> polynomalActor = Actor::createActor("Polynomal");
|
|
QVERIFY(polynomalActor != nullptr);
|
|
|
|
std::shared_ptr<Actor> scriptActor = Actor::createActor("Script");
|
|
QVERIFY(scriptActor != nullptr);
|
|
|
|
std::shared_ptr<Actor> genericActor = Actor::createActor("Actor");
|
|
QVERIFY(genericActor != nullptr);
|
|
|
|
// Test unknown type returns nullptr
|
|
std::shared_ptr<Actor> unknownActor = Actor::createActor("UnknownType");
|
|
QVERIFY(unknownActor == nullptr);
|
|
}
|
|
|
|
void testActorLoadActor()
|
|
{
|
|
QJsonObject json;
|
|
json["Type"] = "Timer";
|
|
json["Active"] = true;
|
|
json["Exausted"] = false;
|
|
json["TriggerValue"] = 1;
|
|
json["Timeout"] = 5000;
|
|
|
|
std::shared_ptr<Actor> actor = Actor::loadActor(json);
|
|
QVERIFY(actor != nullptr);
|
|
|
|
// Verify the actor was loaded with correct values
|
|
QVERIFY(actor->isActive());
|
|
QVERIFY(!actor->isExausted());
|
|
QVERIFY(actor->getTriggerValue() == 1);
|
|
}
|
|
|
|
void testTimerActorCreation()
|
|
{
|
|
TimerActor actor(60);
|
|
|
|
// Default timeout should be 60 seconds
|
|
QVERIFY(actor.getTimeout() == 60);
|
|
}
|
|
|
|
void testTimerActorSetTimeout()
|
|
{
|
|
TimerActor actor(60);
|
|
|
|
actor.setTimeout(120);
|
|
QVERIFY(actor.getTimeout() == 120);
|
|
|
|
actor.setTimeout(5);
|
|
QVERIFY(actor.getTimeout() == 5);
|
|
}
|
|
|
|
void testTimerActorJsonSerialization()
|
|
{
|
|
TimerActor actor(120);
|
|
|
|
QJsonObject json;
|
|
actor.store(json);
|
|
|
|
// Verify JSON contents
|
|
QVERIFY(json.contains("Type"));
|
|
QVERIFY(json.contains("Timeout"));
|
|
|
|
QVERIFY(json["Type"].toString() == "Timer");
|
|
QVERIFY(json["Timeout"].toInt() == 120000); // Converted to milliseconds
|
|
}
|
|
|
|
void testTimerActorJsonDeserialization()
|
|
{
|
|
QJsonObject json;
|
|
json["Type"] = "Timer";
|
|
json["Timeout"] = 30000; // 30 seconds in milliseconds
|
|
json["Active"] = true;
|
|
json["Exausted"] = false;
|
|
json["TriggerValue"] = 1;
|
|
|
|
TimerActor actor;
|
|
actor.load(json, false);
|
|
|
|
// Timeout should be 30 seconds
|
|
QVERIFY(actor.getTimeout() == 30);
|
|
}
|
|
|
|
void testTimerActorGetName()
|
|
{
|
|
TimerActor actor(60);
|
|
|
|
QString name = actor.getName();
|
|
QVERIFY(name.contains("60"));
|
|
}
|
|
|
|
void testSensorActorCreation()
|
|
{
|
|
Sensor sensor(Sensor::TYPE_TEMPERATURE, 1, 25.0, "temp_sensor");
|
|
SensorActor actor(sensor);
|
|
|
|
// Verify sensor was set correctly
|
|
QVERIFY(actor.getSensor().type == Sensor::TYPE_TEMPERATURE);
|
|
QVERIFY(actor.getSensor().id == 1);
|
|
}
|
|
|
|
void testSensorActorDefaultCreation()
|
|
{
|
|
SensorActor actor;
|
|
|
|
// Default sensor should be dummy
|
|
QVERIFY(actor.getSensor().type == Sensor::TYPE_DUMMY);
|
|
}
|
|
|
|
void testSensorActorSetSensor()
|
|
{
|
|
SensorActor actor;
|
|
|
|
Sensor newSensor(Sensor::TYPE_HUMIDITY, 2, 60.0, "humidity_sensor");
|
|
actor.setSensor(newSensor);
|
|
|
|
QVERIFY(actor.getSensor().type == Sensor::TYPE_HUMIDITY);
|
|
QVERIFY(actor.getSensor().id == 2);
|
|
}
|
|
|
|
void testSensorActorSetThreshold()
|
|
{
|
|
SensorActor actor;
|
|
|
|
actor.setThreshold(25.0);
|
|
QVERIFY(actor.getThreshold() == 25.0);
|
|
}
|
|
|
|
void testSensorActorSetSlope()
|
|
{
|
|
SensorActor actor;
|
|
|
|
actor.setSloap(SensorActor::SLOPE_UP);
|
|
QVERIFY(actor.getSloap() == SensorActor::SLOPE_UP);
|
|
|
|
actor.setSloap(SensorActor::SLOPE_DOWN);
|
|
QVERIFY(actor.getSloap() == SensorActor::SLOPE_DOWN);
|
|
|
|
actor.setSloap(SensorActor::SLOPE_BOTH);
|
|
QVERIFY(actor.getSloap() == SensorActor::SLOPE_BOTH);
|
|
}
|
|
|
|
void testSensorActorJsonSerialization()
|
|
{
|
|
Sensor sensor(Sensor::TYPE_TEMPERATURE, 1, 25.0, "temp_sensor");
|
|
SensorActor actor(sensor);
|
|
actor.setThreshold(30.0);
|
|
actor.setSloap(SensorActor::SLOPE_UP);
|
|
|
|
QJsonObject json;
|
|
actor.store(json);
|
|
|
|
// Verify JSON contents
|
|
QVERIFY(json.contains("Type"));
|
|
QVERIFY(json.contains("Threshold"));
|
|
QVERIFY(json.contains("Sloap"));
|
|
QVERIFY(json.contains("SensorType"));
|
|
|
|
QVERIFY(json["Type"].toString() == "Sensor");
|
|
QVERIFY(json["Threshold"].toDouble() == 30.0);
|
|
QVERIFY(json["Sloap"].toInt() == SensorActor::SLOPE_UP);
|
|
}
|
|
|
|
void testSensorActorJsonDeserialization()
|
|
{
|
|
QJsonObject json;
|
|
json["Type"] = "Sensor";
|
|
json["Threshold"] = 25.5;
|
|
json["Sloap"] = SensorActor::SLOPE_DOWN;
|
|
json["SensorType"] = Sensor::TYPE_HUMIDITY;
|
|
json["SensorId"] = 3;
|
|
json["SensorField"] = 65.0;
|
|
json["SensorName"] = "humidity";
|
|
json["Active"] = true;
|
|
json["Exausted"] = false;
|
|
json["TriggerValue"] = 1;
|
|
|
|
SensorActor actor;
|
|
actor.load(json, false);
|
|
|
|
QVERIFY(actor.getThreshold() == 25.5);
|
|
QVERIFY(actor.getSloap() == SensorActor::SLOPE_DOWN);
|
|
}
|
|
|
|
void testSensorActorGetName()
|
|
{
|
|
Sensor sensor(Sensor::TYPE_TEMPERATURE, 1, 25.0, "temp_sensor");
|
|
SensorActor actor(sensor);
|
|
actor.setThreshold(30.0);
|
|
|
|
QString name = actor.getName();
|
|
QVERIFY(name.contains("temp_sensor"));
|
|
QVERIFY(name.contains("30"));
|
|
}
|
|
|
|
// ScriptActor tests
|
|
void testScriptActorCreation()
|
|
{
|
|
ScriptActor actor;
|
|
|
|
// Should start with empty sensors
|
|
QVERIFY(actor.getSensors().isEmpty());
|
|
|
|
// Should not watch parent item by default
|
|
QVERIFY(!actor.getWatchParentItem());
|
|
|
|
// Script path and code should be empty
|
|
QVERIFY(actor.getScriptPath().isEmpty());
|
|
QVERIFY(actor.getScriptCode().isEmpty());
|
|
}
|
|
|
|
void testScriptActorSensors()
|
|
{
|
|
ScriptActor actor;
|
|
|
|
// Add sensors
|
|
Sensor sensor1(Sensor::TYPE_TEMPERATURE, 1, 25.0, "temp1");
|
|
Sensor sensor2(Sensor::TYPE_HUMIDITY, 2, 60.0, "humidity");
|
|
|
|
actor.addSensor(sensor1);
|
|
actor.addSensor(sensor2);
|
|
|
|
QVERIFY(actor.getSensors().size() == 2);
|
|
|
|
// Adding duplicate (same type+id) should not add again
|
|
Sensor sensor1Duplicate(Sensor::TYPE_TEMPERATURE, 1, 30.0, "temp1_dup");
|
|
actor.addSensor(sensor1Duplicate);
|
|
QVERIFY(actor.getSensors().size() == 2);
|
|
|
|
// Remove sensor
|
|
actor.removeSensor(sensor1);
|
|
QVERIFY(actor.getSensors().size() == 1);
|
|
QVERIFY(actor.getSensors()[0].type == Sensor::TYPE_HUMIDITY);
|
|
|
|
// Clear sensors
|
|
actor.clearSensors();
|
|
QVERIFY(actor.getSensors().isEmpty());
|
|
}
|
|
|
|
void testScriptActorSensorMatching()
|
|
{
|
|
ScriptActor actor;
|
|
|
|
// Add a temperature sensor with id 5
|
|
Sensor watchedSensor(Sensor::TYPE_TEMPERATURE, 5, 20.0, "watched_temp");
|
|
actor.addSensor(watchedSensor);
|
|
|
|
// A different temperature sensor (id 10) should NOT match
|
|
Sensor otherTempSensor(Sensor::TYPE_TEMPERATURE, 10, 25.0, "other_temp");
|
|
QVERIFY(!(otherTempSensor.type == watchedSensor.type && otherTempSensor.id == watchedSensor.id));
|
|
|
|
// A humidity sensor with same id (5) should NOT match
|
|
Sensor sameIdHumidity(Sensor::TYPE_HUMIDITY, 5, 50.0, "humidity_same_id");
|
|
QVERIFY(!(sameIdHumidity.type == watchedSensor.type && sameIdHumidity.id == watchedSensor.id));
|
|
}
|
|
|
|
void testScriptActorWatchParentItem()
|
|
{
|
|
ScriptActor actor;
|
|
|
|
QVERIFY(!actor.getWatchParentItem());
|
|
|
|
actor.setWatchParentItem(true);
|
|
QVERIFY(actor.getWatchParentItem());
|
|
|
|
actor.setWatchParentItem(false);
|
|
QVERIFY(!actor.getWatchParentItem());
|
|
}
|
|
|
|
void testScriptActorScriptPath()
|
|
{
|
|
ScriptActor actor;
|
|
|
|
QVERIFY(actor.getScriptPath().isEmpty());
|
|
|
|
actor.setScriptPath("/path/to/script.py");
|
|
QVERIFY(actor.getScriptPath() == "/path/to/script.py");
|
|
}
|
|
|
|
void testScriptActorScriptCode()
|
|
{
|
|
ScriptActor actor;
|
|
|
|
QVERIFY(actor.getScriptCode().isEmpty());
|
|
|
|
actor.setScriptCode("return 42");
|
|
QVERIFY(actor.getScriptCode() == "return 42");
|
|
}
|
|
|
|
void testScriptActorJsonSerialization()
|
|
{
|
|
ScriptActor actor;
|
|
actor.setWatchParentItem(true);
|
|
actor.setScriptPath("/path/to/script.py");
|
|
actor.setScriptCode("return 1");
|
|
|
|
Sensor sensor1(Sensor::TYPE_TEMPERATURE, 1, 25.0, "temp1");
|
|
Sensor sensor2(Sensor::TYPE_HUMIDITY, 2, 60.0, "humidity");
|
|
actor.addSensor(sensor1);
|
|
actor.addSensor(sensor2);
|
|
|
|
QJsonObject json;
|
|
actor.store(json);
|
|
|
|
// Verify JSON contents
|
|
QVERIFY(json["Type"].toString() == "Script");
|
|
QVERIFY(json["WatchParentItem"].toBool() == true);
|
|
QVERIFY(json["ScriptPath"].toString() == "/path/to/script.py");
|
|
QVERIFY(json["ScriptCode"].toString() == "return 1");
|
|
|
|
QVERIFY(json.contains("Sensors"));
|
|
QJsonArray sensorsArray = json["Sensors"].toArray();
|
|
QVERIFY(sensorsArray.size() == 2);
|
|
|
|
// Check first sensor
|
|
QVERIFY(sensorsArray[0].toObject()["Type"].toInt() == Sensor::TYPE_TEMPERATURE);
|
|
QVERIFY(sensorsArray[0].toObject()["Id"].toInteger() == 1);
|
|
}
|
|
|
|
void testScriptActorJsonDeserialization()
|
|
{
|
|
QJsonObject json;
|
|
json["Type"] = "Script";
|
|
json["WatchParentItem"] = true;
|
|
json["ScriptPath"] = "/custom/script.py";
|
|
json["ScriptCode"] = "return 99";
|
|
json["Active"] = true;
|
|
json["Exausted"] = false;
|
|
json["TriggerValue"] = 5;
|
|
|
|
QJsonArray sensorsArray;
|
|
QJsonObject sensor1;
|
|
sensor1["Type"] = Sensor::TYPE_TEMPERATURE;
|
|
sensor1["Id"] = 10;
|
|
sensor1["Name"] = "loaded_temp";
|
|
sensorsArray.append(sensor1);
|
|
json["Sensors"] = sensorsArray;
|
|
|
|
ScriptActor actor;
|
|
actor.load(json, false);
|
|
|
|
QVERIFY(actor.getWatchParentItem() == true);
|
|
QVERIFY(actor.getScriptPath() == "/custom/script.py");
|
|
QVERIFY(actor.getScriptCode() == "return 99");
|
|
QVERIFY(actor.getTriggerValue() == 5);
|
|
QVERIFY(actor.isActive() == true);
|
|
|
|
QVERIFY(actor.getSensors().size() == 1);
|
|
QVERIFY(actor.getSensors()[0].type == Sensor::TYPE_TEMPERATURE);
|
|
QVERIFY(actor.getSensors()[0].id == 10);
|
|
QVERIFY(actor.getSensors()[0].name == "loaded_temp");
|
|
}
|
|
|
|
void testScriptActorLoadActor()
|
|
{
|
|
QJsonObject json;
|
|
json["Type"] = "Script";
|
|
json["WatchParentItem"] = false;
|
|
json["ScriptCode"] = "return 42";
|
|
json["Active"] = true;
|
|
json["Exausted"] = false;
|
|
json["TriggerValue"] = 1;
|
|
|
|
std::shared_ptr<Actor> actor = Actor::loadActor(json);
|
|
QVERIFY(actor != nullptr);
|
|
|
|
// Verify the actor was loaded with correct values
|
|
QVERIFY(actor->isActive());
|
|
QVERIFY(!actor->isExausted());
|
|
QVERIFY(actor->getTriggerValue() == 1);
|
|
}
|
|
|
|
void testScriptActorGetName()
|
|
{
|
|
ScriptActor actor;
|
|
|
|
// Without sensors, name should just be "Script"
|
|
QString name = actor.getName();
|
|
QVERIFY(name == "Script");
|
|
|
|
// With sensors
|
|
Sensor sensor1(Sensor::TYPE_TEMPERATURE, 1, 25.0, "temp_sensor");
|
|
actor.addSensor(sensor1);
|
|
|
|
name = actor.getName();
|
|
QVERIFY(name.contains("Script"));
|
|
QVERIFY(name.contains("temp_sensor"));
|
|
|
|
// With parent item watching
|
|
actor.setWatchParentItem(true);
|
|
name = actor.getName();
|
|
QVERIFY(name.contains("parent item"));
|
|
}
|
|
|
|
void testScriptActorTriggerSync()
|
|
{
|
|
ScriptActor actor;
|
|
actor.setTriggerValue(5);
|
|
|
|
// triggerSync should not crash
|
|
// It emits sigItemUpdate which will be handled by parent item
|
|
actor.triggerSync();
|
|
|
|
// Verify trigger value is unchanged
|
|
QVERIFY(actor.getTriggerValue() == 5);
|
|
}
|
|
|
|
void testScriptActorRunScript()
|
|
{
|
|
ScriptActor actor;
|
|
actor.setTriggerValue(0);
|
|
|
|
// Set a simple script that returns 42
|
|
actor.setScriptCode("return 42");
|
|
|
|
// Run the script
|
|
QVariant result = actor.runScriptNow();
|
|
|
|
// Verify the result is 42
|
|
QVERIFY(result.isValid());
|
|
QVERIFY(result.toInt() == 42);
|
|
|
|
// Note: performValueAction emits sigItemUpdate but doesn't update triggerValue
|
|
// triggerValue is set manually and used for manual activation
|
|
}
|
|
|
|
void testScriptActorRunScriptWithDicts()
|
|
{
|
|
ScriptActor actor;
|
|
actor.setTriggerValue(0);
|
|
|
|
// Set a script that uses the available dicts
|
|
actor.setScriptCode("return len(items) + len(sensors)");
|
|
|
|
// Run the script - should not crash
|
|
QVariant result = actor.runScriptNow();
|
|
|
|
// Result should be valid (number of items + sensors)
|
|
QVERIFY(result.isValid());
|
|
}
|
|
|
|
void testScriptActorRunScriptMultipleTimes()
|
|
{
|
|
ScriptActor actor;
|
|
actor.setTriggerValue(0);
|
|
|
|
// Set a script that increments
|
|
actor.setScriptCode("return 1");
|
|
|
|
// Run multiple times - should not crash
|
|
for(int i = 0; i < 3; i++)
|
|
{
|
|
QVariant result = actor.runScriptNow();
|
|
QVERIFY(result.isValid());
|
|
QVERIFY(result.toInt() == 1);
|
|
}
|
|
}
|
|
|
|
void cleanupTestCase()
|
|
{
|
|
// Cleanup after all tests
|
|
}
|
|
};
|
|
|
|
QTEST_APPLESS_MAIN(TestActor)
|
|
|
|
#include "test_actor.moc" |