From 5a7669481945f29e2f015a4036177554336fc452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 10 Jul 2015 16:58:28 +0200 Subject: [PATCH] launch_daemon: Added events parsing. * Including tests, also for the environment parsing. --- src/servers/launch/SettingsParser.cpp | 79 +++++++--- src/tests/servers/launch/Jamfile | 6 +- .../servers/launch/SettingsParserTest.cpp | 137 +++++++++++++++++- src/tests/servers/launch/SettingsParserTest.h | 11 ++ 4 files changed, 207 insertions(+), 26 deletions(-) diff --git a/src/servers/launch/SettingsParser.cpp b/src/servers/launch/SettingsParser.cpp index 8c81edf39d..fcc631eba7 100644 --- a/src/servers/launch/SettingsParser.cpp +++ b/src/servers/launch/SettingsParser.cpp @@ -9,7 +9,37 @@ #include -class ConditionConverter : public DriverSettingsConverter { +class AbstractArgsConverter : public DriverSettingsConverter { +public: + status_t ConvertEmptyFromDriverSettings( + const driver_parameter& parameter, const char* name, uint32 type, + BMessage& target) + { + if (parameter.parameter_count != 0) + return B_OK; + + BMessage message; + return target.AddMessage(name, &message); + } + +protected: + status_t AddSubMessage(const driver_parameter& parameter, int32 index, + BMessage& target) + { + const char* condition = parameter.values[index]; + BMessage args; + for (index++; index < parameter.value_count; index++) { + status_t status = args.AddString("args", + parameter.values[index]); + if (status != B_OK) + return status; + } + return target.AddMessage(condition, &args); + } +}; + + +class ConditionConverter : public AbstractArgsConverter { public: status_t ConvertFromDriverSettings(const driver_parameter& parameter, const char* name, int32 index, uint32 type, BMessage& target) @@ -29,7 +59,7 @@ public: index++; } - status_t status = _AddSubMessage(parameter, index, *add); + status_t status = AddSubMessage(parameter, index, *add); if (status == B_OK && not) status = target.AddMessage("not", &message); @@ -39,37 +69,31 @@ public: if (index != 0) return B_OK; - return _AddSubMessage(parameter, index, target); + return AddSubMessage(parameter, index, target); } message.AddString("args", parameter.values[index]); return target.AddMessage(parameter.name, &message); } +}; - status_t ConvertEmptyFromDriverSettings( - const driver_parameter& parameter, const char* name, uint32 type, - BMessage& target) + +class EventConverter : public AbstractArgsConverter { +public: + status_t ConvertFromDriverSettings(const driver_parameter& parameter, + const char* name, int32 index, uint32 type, BMessage& target) { - if (parameter.parameter_count != 0) - return B_OK; - BMessage message; - return target.AddMessage(name, &message); - } + if (strcmp(parameter.name, "on") == 0) { + // Parse values directly following "on" + if (index != 0) + return B_OK; -private: - status_t _AddSubMessage(const driver_parameter& parameter, int32 index, - BMessage& target) - { - const char* condition = parameter.values[index]; - BMessage args; - for (index++; index < parameter.value_count; index++) { - status_t status = args.AddString("args", - parameter.values[index]); - if (status != B_OK) - return status; + return AddSubMessage(parameter, index, target); } - return target.AddMessage(condition, &args); + + message.AddString("args", parameter.values[index]); + return target.AddMessage(parameter.name, &message); } }; @@ -105,6 +129,13 @@ const static settings_template kConditionTemplate[] = { {0, NULL, NULL} }; +const static settings_template kEventTemplate[] = { + {B_STRING_TYPE, NULL, NULL, true, new EventConverter()}, + {B_MESSAGE_TYPE, "and", kEventTemplate}, + {B_MESSAGE_TYPE, "or", kEventTemplate}, + {0, NULL, NULL} +}; + const static settings_template kPortTemplate[] = { {B_STRING_TYPE, "name", NULL, true}, {B_INT32_TYPE, "capacity", NULL}, @@ -122,6 +153,7 @@ const static settings_template kJobTemplate[] = { {B_STRING_TYPE, "requires", NULL}, {B_BOOL_TYPE, "legacy", NULL}, {B_MESSAGE_TYPE, "port", kPortTemplate}, + {B_MESSAGE_TYPE, "on", kEventTemplate}, {B_MESSAGE_TYPE, "if", kConditionTemplate}, {B_BOOL_TYPE, "no_safemode", NULL}, {B_MESSAGE_TYPE, "env", kEnvTemplate}, @@ -131,6 +163,7 @@ const static settings_template kJobTemplate[] = { const static settings_template kTargetTemplate[] = { {B_STRING_TYPE, "name", NULL, true}, {B_BOOL_TYPE, "reset", NULL}, + {B_MESSAGE_TYPE, "on", kEventTemplate}, {B_MESSAGE_TYPE, "if", kConditionTemplate}, {B_BOOL_TYPE, "no_safemode", NULL}, {B_MESSAGE_TYPE, "env", kEnvTemplate}, diff --git a/src/tests/servers/launch/Jamfile b/src/tests/servers/launch/Jamfile index e0fb10eee7..f530bf6bb2 100644 --- a/src/tests/servers/launch/Jamfile +++ b/src/tests/servers/launch/Jamfile @@ -10,10 +10,12 @@ UnitTestLib liblaunch_daemontest.so : LaunchDaemonTestAddon.cpp SettingsParserTest.cpp - SettingsParser.cpp - ConditionsTest.cpp + + # from the launch_daemon + SettingsParser.cpp Conditions.cpp + Utility.cpp : be libshared.a [ TargetLibstdc++ ] [ TargetLibsupc++ ] ; diff --git a/src/tests/servers/launch/SettingsParserTest.cpp b/src/tests/servers/launch/SettingsParserTest.cpp index add04b9fdb..aa34478c1d 100644 --- a/src/tests/servers/launch/SettingsParserTest.cpp +++ b/src/tests/servers/launch/SettingsParserTest.cpp @@ -27,6 +27,9 @@ SettingsParserTest::~SettingsParserTest() } +// #pragma mark - conditions + + void SettingsParserTest::TestConditionsMultiLine() { @@ -178,6 +181,101 @@ SettingsParserTest::TestConditionsMultiLineNot() } +// #pragma mark - events + + +void +SettingsParserTest::TestEventsMultiLine() +{ + BMessage message; + CPPUNIT_ASSERT_EQUAL(B_OK, _ParseEvent("on {\n" + "\tfile_created one\n" + "\tdemand\n" + "}\n", message)); + CPPUNIT_ASSERT_EQUAL(2, message.CountNames(B_ANY_TYPE)); + + BMessage subMessage; + CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("demand", &subMessage)); + CPPUNIT_ASSERT(subMessage.IsEmpty()); + + CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("file_created", + &subMessage)); + CPPUNIT_ASSERT_EQUAL(BString("one"), + BString(subMessage.GetString("args", 0, "-"))); + CPPUNIT_ASSERT_EQUAL(1, subMessage.CountNames(B_ANY_TYPE)); +} + + +void +SettingsParserTest::TestEventsFlat() +{ + BMessage message; + CPPUNIT_ASSERT_EQUAL(B_OK, _ParseEvent("on demand\n", message)); + CPPUNIT_ASSERT_EQUAL(1, message.CountNames(B_ANY_TYPE)); + + BMessage args; + CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("demand", &args)); + CPPUNIT_ASSERT(args.IsEmpty()); +} + + +void +SettingsParserTest::TestEventsFlatWithArgs() +{ + BMessage message; + CPPUNIT_ASSERT_EQUAL(B_OK, _ParseEvent("on file_created one\n", message)); + CPPUNIT_ASSERT_EQUAL(1, message.CountNames(B_ANY_TYPE)); + + BMessage args; + CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("file_created", &args)); + CPPUNIT_ASSERT_EQUAL(BString("one"), + BString(args.GetString("args", 0, "-"))); + CPPUNIT_ASSERT_EQUAL(1, args.CountNames(B_ANY_TYPE)); +} + + +// #pragma mark - environment + + +void +SettingsParserTest::TestEnvironmentMultiLine() +{ + BMessage message; + CPPUNIT_ASSERT_EQUAL(B_OK, _ParseName("env", "env {\n" + "from_script SetupEnvironment\n" + "TEST well, yes\n" + "}\n", message)); + CPPUNIT_ASSERT_EQUAL(2, message.CountNames(B_ANY_TYPE)); + + CPPUNIT_ASSERT_EQUAL(BString("SetupEnvironment"), + BString(message.GetString("from_script", "-"))); + CPPUNIT_ASSERT_EQUAL(1, _ArrayCount(message, "from_script")); + + CPPUNIT_ASSERT_EQUAL(BString("well,"), + BString(message.GetString("TEST", 0, "-"))); + CPPUNIT_ASSERT_EQUAL(BString("yes"), + BString(message.GetString("TEST", 1, "-"))); + CPPUNIT_ASSERT_EQUAL(2, _ArrayCount(message, "TEST")); +} + + +void +SettingsParserTest::TestEnvironmentFlat() +{ + BMessage message; + CPPUNIT_ASSERT_EQUAL(B_OK, _ParseName("env", "env SetupEnvironment\n", + message)); + CPPUNIT_ASSERT_EQUAL(1, message.CountNames(B_ANY_TYPE)); + + CPPUNIT_ASSERT_EQUAL(BString("SetupEnvironment"), + BString(message.GetString("from_script", "-"))); + CPPUNIT_ASSERT_EQUAL(1, _ArrayCount(message, "from_script")); +} + + +// #pragma mark - run + + void SettingsParserTest::TestRunFlat() { @@ -288,6 +386,9 @@ SettingsParserTest::TestRunIfThenElseMultiLine() } +// #pragma mark - + + /*static*/ void SettingsParserTest::AddTests(BTestSuite& parent) { @@ -319,6 +420,25 @@ SettingsParserTest::AddTests(BTestSuite& parent) "SettingsParserTest::TestConditionsMultiLineNot", &SettingsParserTest::TestConditionsMultiLineNot)); + // Events + suite.addTest(new CppUnit::TestCaller( + "SettingsParserTest::TestEventsMultiLine", + &SettingsParserTest::TestEventsMultiLine)); + suite.addTest(new CppUnit::TestCaller( + "SettingsParserTest::TestEventsFlat", + &SettingsParserTest::TestEventsFlat)); + suite.addTest(new CppUnit::TestCaller( + "SettingsParserTest::TestEventsFlatWithArgs", + &SettingsParserTest::TestEventsFlatWithArgs)); + + // Environment + suite.addTest(new CppUnit::TestCaller( + "SettingsParserTest::TestEnvironmentMultiLine", + &SettingsParserTest::TestEnvironmentMultiLine)); + suite.addTest(new CppUnit::TestCaller( + "SettingsParserTest::TestEnvironmentFlat", + &SettingsParserTest::TestEnvironmentFlat)); + // Run suite.addTest(new CppUnit::TestCaller( "SettingsParserTest::TestRunFlat", @@ -339,6 +459,21 @@ SettingsParserTest::AddTests(BTestSuite& parent) status_t SettingsParserTest::_ParseCondition(const char* text, BMessage& message) +{ + return _ParseName("if", text, message); +} + + +status_t +SettingsParserTest::_ParseEvent(const char* text, BMessage& message) +{ + return _ParseName("on", text, message); +} + + +status_t +SettingsParserTest::_ParseName(const char* name, const char* text, + BMessage& message) { SettingsParser parser; BString input("job A {\n"); @@ -357,7 +492,7 @@ SettingsParserTest::_ParseCondition(const char* text, BMessage& message) CPPUNIT_ASSERT_EQUAL(2, job.CountNames(B_ANY_TYPE)); CPPUNIT_ASSERT_EQUAL(BString("A"), BString(job.GetString("name"))); - return job.FindMessage("if", &message); + return job.FindMessage(name, &message); } diff --git a/src/tests/servers/launch/SettingsParserTest.h b/src/tests/servers/launch/SettingsParserTest.h index d9ffa391d4..634c07aba5 100644 --- a/src/tests/servers/launch/SettingsParserTest.h +++ b/src/tests/servers/launch/SettingsParserTest.h @@ -26,6 +26,13 @@ public: void TestConditionsMultiLineFlatNotWithArgs(); void TestConditionsMultiLineNot(); + void TestEventsMultiLine(); + void TestEventsFlat(); + void TestEventsFlatWithArgs(); + + void TestEnvironmentMultiLine(); + void TestEnvironmentFlat(); + void TestRunFlat(); void TestRunMultiLine(); void TestRunIfThenElseFlat(); @@ -36,6 +43,10 @@ public: private: status_t _ParseCondition(const char* text, BMessage& message); + status_t _ParseEvent(const char* text, + BMessage& message); + status_t _ParseName(const char* name, const char* text, + BMessage& message); int32 _ArrayCount(BMessage& message, const char* name); };