Inial python script actor implementation
This commit is contained in:
parent
45676b3384
commit
3df91cc73d
331 changed files with 99399 additions and 5 deletions
|
|
@ -2,6 +2,8 @@
|
|||
#include "actors/actor.h"
|
||||
#include "actors/timeractor.h"
|
||||
#include "actors/sensoractor.h"
|
||||
#include "actors/scriptactor.h"
|
||||
#include "sensors/sensor.h"
|
||||
|
||||
class TestActor : public QObject
|
||||
{
|
||||
|
|
@ -131,8 +133,8 @@ private slots:
|
|||
std::shared_ptr<Actor> polynomalActor = Actor::createActor("Polynomal");
|
||||
QVERIFY(polynomalActor != nullptr);
|
||||
|
||||
std::shared_ptr<Actor> factorActor = Actor::createActor("MultiFactor");
|
||||
QVERIFY(factorActor != nullptr);
|
||||
std::shared_ptr<Actor> scriptActor = Actor::createActor("Script");
|
||||
QVERIFY(scriptActor != nullptr);
|
||||
|
||||
std::shared_ptr<Actor> genericActor = Actor::createActor("Actor");
|
||||
QVERIFY(genericActor != nullptr);
|
||||
|
|
@ -322,6 +324,269 @@ private slots:
|
|||
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue