[haiku-commits] BRANCH axeld-github.launch_daemon [196b0c640f67] src/tests/servers/launch src/servers/launch data/launch

  • From: axeld-github.launch_daemon <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 24 Jun 2015 22:01:48 +0200 (CEST)

added 6 changesets to branch 'refs/remotes/axeld-github/launch_daemon'
old head: 9b3193598ae736542f5a07d2d542b005f1182b16
new head: 196b0c640f67ce41705bd6b1491d6699800436ae
overview: https://github.com/axeld/haiku/compare/9b3193598ae7...196b0c640f67

----------------------------------------------------------------------------

479d26c03e96: launch_daemon: Make sure conditions are properly deleted.

d89a2eea2760: launch_daemon: Actually set the conditions.

01a5ae72955b: launch_daemon: Added condition tests.

40ff4e0a07ff: Sudoku: Improved value hint.

* Removed toggling its visibility on click - it's now always visible
once it's there.
* Also update and show it when changing a value or hint.

38679dbd2871: launch_daemon: Added Condition::ToString() method.

* For debugging purposes only.

196b0c640f67: launch_daemon: Added run directive.

* Allows to conditionally (or unconditionally) launch targets.
* Including tests for the settings parser.
* FirstBootPrompt is now launched when deemed necessary (as in
the Bootscript).

[ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

14 files changed, 627 insertions(+), 41 deletions(-)
data/launch/user | 36 +++-
src/apps/sudoku/SudokuView.cpp | 4 +-
src/servers/launch/BaseJob.cpp | 6 +
src/servers/launch/BaseJob.h | 1 +
src/servers/launch/Conditions.cpp | 82 +++++++++
src/servers/launch/Conditions.h | 4 +
src/servers/launch/LaunchDaemon.cpp | 141 +++++++++++----
src/servers/launch/SettingsParser.cpp | 37 ++++
src/tests/servers/launch/ConditionsTest.cpp | 170 +++++++++++++++++++
src/tests/servers/launch/ConditionsTest.h | 34 ++++
src/tests/servers/launch/Jamfile | 5 +-
.../servers/launch/LaunchDaemonTestAddon.cpp | 2 +
src/tests/servers/launch/SettingsParserTest.cpp | 139 ++++++++++++++-
src/tests/servers/launch/SettingsParserTest.h | 7 +

############################################################################

Commit: 479d26c03e96b08f2de74ddb7f1ef30c3cfa4c3b
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Wed Jun 24 07:09:15 2015 UTC

launch_daemon: Make sure conditions are properly deleted.

----------------------------------------------------------------------------

diff --git a/src/servers/launch/BaseJob.cpp b/src/servers/launch/BaseJob.cpp
index 5039855..2dbec44a 100644
--- a/src/servers/launch/BaseJob.cpp
+++ b/src/servers/launch/BaseJob.cpp
@@ -17,6 +17,12 @@ BaseJob::BaseJob(const char* name)
}


+BaseJob::~BaseJob()
+{
+ delete fCondition;
+}
+
+
const char*
BaseJob::Name() const
{
diff --git a/src/servers/launch/BaseJob.h b/src/servers/launch/BaseJob.h
index f410814..df08964 100644
--- a/src/servers/launch/BaseJob.h
+++ b/src/servers/launch/BaseJob.h
@@ -18,6 +18,7 @@ class ConditionContext;
class BaseJob : public BJob {
public:
BaseJob(const
char* name);
+ ~BaseJob();

const char* Name() const;

diff --git a/src/servers/launch/Conditions.cpp
b/src/servers/launch/Conditions.cpp
index 6611f30..8c6c09c 100644
--- a/src/servers/launch/Conditions.cpp
+++ b/src/servers/launch/Conditions.cpp
@@ -119,6 +119,8 @@ Condition::~Condition()


ConditionContainer::ConditionContainer(const BMessage& args)
+ :
+ fConditions(10, true)
{
char* name;
type_code type;

############################################################################

Commit: d89a2eea27608adb1bc66399cb1856d8cfc5ff90
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Wed Jun 24 07:19:28 2015 UTC

launch_daemon: Actually set the conditions.

----------------------------------------------------------------------------

diff --git a/src/servers/launch/LaunchDaemon.cpp
b/src/servers/launch/LaunchDaemon.cpp
index 38b9841..3c92b49 100644
--- a/src/servers/launch/LaunchDaemon.cpp
+++ b/src/servers/launch/LaunchDaemon.cpp
@@ -92,12 +92,14 @@ private:
status_t _ReadFile(const char*
context, BEntry& entry);

void _AddJobs(Target*
target, BMessage& message);
+ void _AddTargets(BMessage&
message);
void _AddJob(Target* target,
bool service,

BMessage& message);
void _InitJobs();
void _LaunchJobs(Target*
target);
void _AddLaunchJob(Job* job);
void _AddTarget(Target*
target);
+ void _SetCondition(BaseJob*
job, BMessage& message);

status_t _StartSession(const
char* login,
const
char* password);
@@ -454,37 +456,7 @@ LaunchDaemon::_ReadFile(const char* context, BEntry& entry)
status = parser.ParseFile(path.Path(), message);
if (status == B_OK) {
_AddJobs(NULL, message);
-
- BMessage targetMessage;
- for (int32 index = 0; message.FindMessage("target", index,
- &targetMessage) == B_OK; index++) {
- const char* name = targetMessage.GetString("name");
- if (name == NULL) {
- // TODO: log error
- debug_printf("Target has no name, ignoring
it!\n");
- continue;
- }
-
- Target* target = FindTarget(name);
- if (target == NULL) {
- target = new Target(name);
- _AddTarget(target);
- } else if (targetMessage.GetBool("reset")) {
- // Remove all jobs from this target
- for (JobMap::iterator iterator = fJobs.begin();
- iterator != fJobs.end();) {
- Job* job = iterator->second;
- JobMap::iterator remove = iterator++;
-
- if (job->Target() == target) {
- fJobs.erase(remove);
- delete job;
- }
- }
- }
-
- _AddJobs(target, targetMessage);
- }
+ _AddTargets(message);
}

return status;
@@ -508,6 +480,43 @@ LaunchDaemon::_AddJobs(Target* target, BMessage& message)


void
+LaunchDaemon::_AddTargets(BMessage& message)
+{
+ BMessage targetMessage;
+ for (int32 index = 0; message.FindMessage("target", index,
+ &targetMessage) == B_OK; index++) {
+ const char* name = targetMessage.GetString("name");
+ if (name == NULL) {
+ // TODO: log error
+ debug_printf("Target has no name, ignoring it!\n");
+ continue;
+ }
+
+ Target* target = FindTarget(name);
+ if (target == NULL) {
+ target = new Target(name);
+ _AddTarget(target);
+ } else if (targetMessage.GetBool("reset")) {
+ // Remove all jobs from this target
+ for (JobMap::iterator iterator = fJobs.begin();
+ iterator != fJobs.end();) {
+ Job* job = iterator->second;
+ JobMap::iterator remove = iterator++;
+
+ if (job->Target() == target) {
+ fJobs.erase(remove);
+ delete job;
+ }
+ }
+ }
+
+ _SetCondition(target, targetMessage);
+ _AddJobs(target, targetMessage);
+ }
+}
+
+
+void
LaunchDaemon::_AddJob(Target* target, bool service, BMessage& message)
{
BString name = message.GetString("name");
@@ -528,6 +537,8 @@ LaunchDaemon::_AddJob(Target* target, bool service,
BMessage& message)
!message.GetBool("no_safemode", !job->LaunchInSafeMode()));
job->SetTarget(target);

+ _SetCondition(job, message);
+
BMessage portMessage;
for (int32 index = 0;
message.FindMessage("port", index, &portMessage) ==
B_OK; index++) {
@@ -611,6 +622,18 @@ LaunchDaemon::_AddTarget(Target* target)
}


+void
+LaunchDaemon::_SetCondition(BaseJob* job, BMessage& message)
+{
+ BMessage conditions;
+ if (message.FindMessage("if", &conditions) == B_OK) {
+ Condition* condition = Conditions::FromMessage(conditions);
+ if (condition != NULL)
+ job->SetCondition(condition);
+ }
+}
+
+
status_t
LaunchDaemon::_StartSession(const char* login, const char* password)
{

############################################################################

Commit: 01a5ae72955b725fe4d68f2ebc8b211e234928fe
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Wed Jun 24 08:49:35 2015 UTC

launch_daemon: Added condition tests.

----------------------------------------------------------------------------

diff --git a/src/tests/servers/launch/ConditionsTest.cpp
b/src/tests/servers/launch/ConditionsTest.cpp
new file mode 100644
index 0000000..0f48382
--- /dev/null
+++ b/src/tests/servers/launch/ConditionsTest.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2015, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "ConditionsTest.h"
+
+#include <stdlib.h>
+
+#include <driver_settings.h>
+#include <String.h>
+
+#include <cppunit/TestCaller.h>
+#include <cppunit/TestSuite.h>
+
+#include "Conditions.h"
+#include "SettingsParser.h"
+
+
+class TestConditionContext : public ConditionContext {
+public:
+ bool IsSafeMode() const
+ {
return false; }
+};
+
+
+static TestConditionContext sConditionContext;
+
+
+ConditionsTest::ConditionsTest()
+{
+}
+
+
+ConditionsTest::~ConditionsTest()
+{
+}
+
+
+void
+ConditionsTest::TestSafemode()
+{
+ Condition* condition = _Condition("safemode");
+ CPPUNIT_ASSERT(!condition->Test(sConditionContext));
+
+ class SafemodeConditionContext : public ConditionContext {
+ public:
+ bool IsSafeMode() const
+ {
+ return true;
+ }
+ } safemodeContext;
+ CPPUNIT_ASSERT(condition->Test(safemodeContext));
+}
+
+
+void
+ConditionsTest::TestFileExists()
+{
+ Condition* condition = _Condition("file_exists /boot");
+ CPPUNIT_ASSERT(condition->Test(sConditionContext));
+
+ condition = _Condition("file_exists /boot/don't fool me!");
+ CPPUNIT_ASSERT(!condition->Test(sConditionContext));
+}
+
+
+void
+ConditionsTest::TestOr()
+{
+ Condition* condition = _Condition("or {\n"
+ "file_exists /boot\n"
+ "}\n");
+ CPPUNIT_ASSERT(condition->Test(sConditionContext));
+
+ condition = _Condition("or {\n"
+ "file_exists /nowhere\n"
+ "}\n");
+ CPPUNIT_ASSERT(!condition->Test(sConditionContext));
+
+ condition = _Condition("or {\n"
+ "file_exists /boot\n"
+ "file_exists /nowhere\n"
+ "}\n");
+ CPPUNIT_ASSERT(condition->Test(sConditionContext));
+}
+
+
+void
+ConditionsTest::TestAnd()
+{
+ Condition* condition = _Condition("and {\n"
+ "file_exists /boot\n"
+ "}\n");
+ CPPUNIT_ASSERT(condition->Test(sConditionContext));
+
+ condition = _Condition("and {\n"
+ "file_exists /nowhere\n"
+ "}\n");
+ CPPUNIT_ASSERT(!condition->Test(sConditionContext));
+
+ condition = _Condition("and {\n"
+ "file_exists /boot\n"
+ "file_exists /nowhere\n"
+ "}\n");
+ CPPUNIT_ASSERT(!condition->Test(sConditionContext));
+}
+
+
+void
+ConditionsTest::TestNot()
+{
+ Condition* condition = _Condition("not safemode");
+ CPPUNIT_ASSERT(condition->Test(sConditionContext));
+
+ class SafemodeConditionContext : public ConditionContext {
+ public:
+ bool IsSafeMode() const
+ {
+ return true;
+ }
+ } safemodeContext;
+ CPPUNIT_ASSERT(!condition->Test(safemodeContext));
+
+}
+
+
+/*static*/ void
+ConditionsTest::AddTests(BTestSuite& parent)
+{
+ CppUnit::TestSuite& suite = *new CppUnit::TestSuite("ConditionsTest");
+
+ suite.addTest(new CppUnit::TestCaller<ConditionsTest>(
+ "ConditionsTest::TestSafemode", &ConditionsTest::TestSafemode));
+ suite.addTest(new CppUnit::TestCaller<ConditionsTest>(
+ "ConditionsTest::TestFileExists",
&ConditionsTest::TestFileExists));
+ suite.addTest(new CppUnit::TestCaller<ConditionsTest>(
+ "ConditionsTest::TestOr", &ConditionsTest::TestOr));
+ suite.addTest(new CppUnit::TestCaller<ConditionsTest>(
+ "ConditionsTest::TestAnd", &ConditionsTest::TestAnd));
+ suite.addTest(new CppUnit::TestCaller<ConditionsTest>(
+ "ConditionsTest::TestNot", &ConditionsTest::TestNot));
+
+ parent.addTest("ConditionsTest", &suite);
+}
+
+
+Condition*
+ConditionsTest::_Condition(const char* string)
+{
+ SettingsParser parser;
+ BString input("job A {\nif {");
+ input << string << "\n}\n}\n";
+
+ BMessage jobs;
+ CPPUNIT_ASSERT_EQUAL(B_OK, parser.Parse(input, jobs));
+
+ BMessage job;
+ CPPUNIT_ASSERT_EQUAL(B_OK, jobs.FindMessage("job", 0, &job));
+ CPPUNIT_ASSERT_EQUAL(2, job.CountNames(B_ANY_TYPE));
+ CPPUNIT_ASSERT_EQUAL(BString("A"), BString(job.GetString("name")));
+
+ BMessage message;
+ CPPUNIT_ASSERT_EQUAL(B_OK, job.FindMessage("if", &message));
+
+ Condition* condition = Conditions::FromMessage(message);
+ CPPUNIT_ASSERT(condition != NULL);
+ return condition;
+}
diff --git a/src/tests/servers/launch/ConditionsTest.h
b/src/tests/servers/launch/ConditionsTest.h
new file mode 100644
index 0000000..4ea14e4
--- /dev/null
+++ b/src/tests/servers/launch/ConditionsTest.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2015, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef CONDITIONS_TEST_H
+#define CONDITIONS_TEST_H
+
+
+#include <TestCase.h>
+#include <TestSuite.h>
+
+
+class Condition;
+
+
+class ConditionsTest : public CppUnit::TestCase {
+public:
+
ConditionsTest();
+ virtual ~ConditionsTest();
+
+ void TestSafemode();
+ void TestFileExists();
+ void TestOr();
+ void TestAnd();
+ void TestNot();
+
+ static void AddTests(BTestSuite& suite);
+
+private:
+ Condition* _Condition(const char*
string);
+};
+
+
+#endif // CONDITIONS_TEST_H
diff --git a/src/tests/servers/launch/Jamfile b/src/tests/servers/launch/Jamfile
index 90be9b7..e0fb10e 100644
--- a/src/tests/servers/launch/Jamfile
+++ b/src/tests/servers/launch/Jamfile
@@ -2,7 +2,7 @@ SubDir HAIKU_TOP src tests servers launch ;

AddSubDirSupportedPlatforms libbe_test ;

-UsePrivateHeaders app shared support ;
+UsePrivateHeaders app shared storage support ;

SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src servers launch ] ;

@@ -12,5 +12,8 @@ UnitTestLib liblaunch_daemontest.so :
SettingsParserTest.cpp
SettingsParser.cpp

+ ConditionsTest.cpp
+ Conditions.cpp
+
: be libshared.a [ TargetLibstdc++ ] [ TargetLibsupc++ ]
;
diff --git a/src/tests/servers/launch/LaunchDaemonTestAddon.cpp
b/src/tests/servers/launch/LaunchDaemonTestAddon.cpp
index 38e272e..497d5f6 100644
--- a/src/tests/servers/launch/LaunchDaemonTestAddon.cpp
+++ b/src/tests/servers/launch/LaunchDaemonTestAddon.cpp
@@ -7,6 +7,7 @@
#include <TestSuite.h>
#include <TestSuiteAddon.h>

+#include "ConditionsTest.h"
#include "SettingsParserTest.h"


@@ -16,6 +17,7 @@ getTestSuite()
BTestSuite* suite = new BTestSuite("LaunchDaemon");

SettingsParserTest::AddTests(*suite);
+ ConditionsTest::AddTests(*suite);

return suite;
}

############################################################################

Commit: 40ff4e0a07ff269824971b3168ee65d8e84724f3
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Wed Jun 24 15:50:59 2015 UTC

Sudoku: Improved value hint.

* Removed toggling its visibility on click - it's now always visible
once it's there.
* Also update and show it when changing a value or hint.

----------------------------------------------------------------------------

diff --git a/src/apps/sudoku/SudokuView.cpp b/src/apps/sudoku/SudokuView.cpp
index fd0adbb..ae12cc3 100644
--- a/src/apps/sudoku/SudokuView.cpp
+++ b/src/apps/sudoku/SudokuView.cpp
@@ -599,8 +599,7 @@ SudokuView::MouseDown(BPoint where)
if (buttons == B_PRIMARY_MOUSE_BUTTON && clicks == 1) {
uint32 value = fField->ValueAt(x, y);
if (value != 0) {
- // Toggle value hint
- _SetValueHintValue(fValueHintValue == value ? ~0UL :
value);
+ _SetValueHintValue(value);
return;
}
}
@@ -612,6 +611,7 @@ SudokuView::MouseDown(BPoint where)
uint32 value = hintX + hintY * fBlockSize;
uint32 field = x + y * fField->Size();
_PushUndo();
+ _SetValueHintValue(value + 1);

if ((clicks == 2 && fLastHintValue == value && fLastField == field)
|| (buttons & (B_SECONDARY_MOUSE_BUTTON

############################################################################

Commit: 38679dbd28716ed27d606537a561a350f24bcdee
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Wed Jun 24 15:52:55 2015 UTC

launch_daemon: Added Condition::ToString() method.

* For debugging purposes only.

----------------------------------------------------------------------------

diff --git a/src/servers/launch/Conditions.cpp
b/src/servers/launch/Conditions.cpp
index 8c6c09c..8cf3d92 100644
--- a/src/servers/launch/Conditions.cpp
+++ b/src/servers/launch/Conditions.cpp
@@ -25,6 +25,9 @@ protected:
void AddCondition(Condition*
condition);

protected:
+ void ToString(BString&
string) const;
+
+protected:
BObjectList<Condition> fConditions;
};

@@ -34,6 +37,7 @@ public:

AndCondition(const BMessage& args);

virtual bool Test(ConditionContext& context)
const;
+ virtual BString ToString() const;
};


@@ -42,6 +46,7 @@ public:

OrCondition(const BMessage& args);

virtual bool Test(ConditionContext& context)
const;
+ virtual BString ToString() const;
};


@@ -50,12 +55,14 @@ public:

NotCondition(const BMessage& args);

virtual bool Test(ConditionContext& context)
const;
+ virtual BString ToString() const;
};


class SafeModeCondition : public Condition {
public:
virtual bool Test(ConditionContext& context)
const;
+ virtual BString ToString() const;
};


@@ -64,6 +71,7 @@ public:

ReadOnlyCondition(const BMessage& args);

virtual bool Test(ConditionContext& context)
const;
+ virtual BString ToString() const;

private:
dev_t fDevice;
@@ -75,6 +83,7 @@ public:

FileExistsCondition(const BMessage& args);

virtual bool Test(ConditionContext& context)
const;
+ virtual BString ToString() const;

private:
BStringList fPaths;
@@ -144,6 +153,20 @@ ConditionContainer::AddCondition(Condition* condition)
}


+void
+ConditionContainer::ToString(BString& string) const
+{
+ string += "[";
+
+ for (int32 index = 0; index < fConditions.CountItems(); index++) {
+ if (index != 0)
+ string += ", ";
+ string += fConditions.ItemAt(index)->ToString();
+ }
+ string += "]";
+}
+
+
// #pragma mark - and


@@ -166,6 +189,15 @@ AndCondition::Test(ConditionContext& context) const
}


+BString
+AndCondition::ToString() const
+{
+ BString string = "and ";
+ ConditionContainer::ToString(string);
+ return string;
+}
+
+
// #pragma mark - or


@@ -191,6 +223,15 @@ OrCondition::Test(ConditionContext& context) const
}


+BString
+OrCondition::ToString() const
+{
+ BString string = "or ";
+ ConditionContainer::ToString(string);
+ return string;
+}
+
+
// #pragma mark - or


@@ -213,6 +254,15 @@ NotCondition::Test(ConditionContext& context) const
}


+BString
+NotCondition::ToString() const
+{
+ BString string = "not ";
+ ConditionContainer::ToString(string);
+ return string;
+}
+
+
// #pragma mark - safemode


@@ -223,6 +273,13 @@ SafeModeCondition::Test(ConditionContext& context) const
}


+BString
+SafeModeCondition::ToString() const
+{
+ return "safemode";
+}
+
+
// #pragma mark - read_only


@@ -257,6 +314,15 @@ ReadOnlyCondition::Test(ConditionContext& context) const
}


+BString
+ReadOnlyCondition::ToString() const
+{
+ BString string = "readonly ";
+ string << fDevice;
+ return string;
+}
+
+
// #pragma mark - file_exists


@@ -282,6 +348,20 @@ FileExistsCondition::Test(ConditionContext& context) const
}


+BString
+FileExistsCondition::ToString() const
+{
+ BString string = "file_exists [";
+ for (int32 index = 0; index < fPaths.CountStrings(); index++) {
+ if (index != 0)
+ string << ", ";
+ string << fPaths.StringAt(index);
+ }
+ string += "]";
+ return string;
+}
+
+
// #pragma mark -


diff --git a/src/servers/launch/Conditions.h b/src/servers/launch/Conditions.h
index b6d1b89..3f779ff 100644
--- a/src/servers/launch/Conditions.h
+++ b/src/servers/launch/Conditions.h
@@ -6,6 +6,9 @@
#define CONDITIONS_H


+#include <String.h>
+
+
class BMessage;


@@ -21,6 +24,7 @@ public:
virtual ~Condition();

virtual bool Test(ConditionContext& context)
const = 0;
+ virtual BString ToString() const = 0;
};



############################################################################

Commit: 196b0c640f67ce41705bd6b1491d6699800436ae
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Wed Jun 24 16:00:32 2015 UTC

launch_daemon: Added run directive.

* Allows to conditionally (or unconditionally) launch targets.
* Including tests for the settings parser.
* FirstBootPrompt is now launched when deemed necessary (as in
the Bootscript).

----------------------------------------------------------------------------

diff --git a/data/launch/user b/data/launch/user
index da21178..dc7a75c 100644
--- a/data/launch/user
+++ b/data/launch/user
@@ -1,9 +1,33 @@
-service x-vnd.Be-TRAK {
- launch /system/Tracker
- legacy
+target desktop {
+ service x-vnd.Be-TRAK {
+ launch /system/Tracker
+ legacy
+ }
+
+ service x-vnd.Be-TSKB {
+ launch /system/Deskbar
+ legacy
+ }
+}
+
+target first_boot {
+ job x-vnd.Haiku-FirstBootPrompt {
+ launch /system/apps/FirstBootPrompt
+ legacy
+ }
}

-service x-vnd.Be-TSKB {
- launch /system/Deskbar
- legacy
+run {
+ if {
+ or {
+ not file_exists /boot/home/config/settings/Locale\
settings
+ read_only
+ }
+ }
+ then {
+ first_boot
+ }
+ else {
+ desktop
+ }
}
diff --git a/src/servers/launch/LaunchDaemon.cpp
b/src/servers/launch/LaunchDaemon.cpp
index 3c92b49..fb2d9be 100644
--- a/src/servers/launch/LaunchDaemon.cpp
+++ b/src/servers/launch/LaunchDaemon.cpp
@@ -93,6 +93,9 @@ private:

void _AddJobs(Target*
target, BMessage& message);
void _AddTargets(BMessage&
message);
+ void
_AddRunTargets(BMessage& message);
+ void
_AddRunTargets(BMessage& message,
+ const
char* name);
void _AddJob(Target* target,
bool service,

BMessage& message);
void _InitJobs();
@@ -112,6 +115,7 @@ private:
private:
JobMap fJobs;
TargetMap fTargets;
+ BStringList fRunTargets;
JobQueue fJobQueue;
SessionMap fSessions;
MainWorker* fMainWorker;
@@ -237,6 +241,13 @@ LaunchDaemon::ReadyToRun()

_InitJobs();
_LaunchJobs(NULL);
+
+ // Launch run targets
+ for (int32 index = 0; index < fRunTargets.CountStrings(); index++) {
+ Target* target = FindTarget(fRunTargets.StringAt(index));
+ if (target != NULL)
+ _LaunchJobs(target);
+ }
}


@@ -457,6 +468,7 @@ LaunchDaemon::_ReadFile(const char* context, BEntry& entry)
if (status == B_OK) {
_AddJobs(NULL, message);
_AddTargets(message);
+ _AddRunTargets(message);
}

return status;
@@ -517,6 +529,50 @@ LaunchDaemon::_AddTargets(BMessage& message)


void
+LaunchDaemon::_AddRunTargets(BMessage& message)
+{
+ BMessage runMessage;
+ for (int32 index = 0; message.FindMessage("run", index,
+ &runMessage) == B_OK; index++) {
+ BMessage conditions;
+ bool pass = true;
+ if (runMessage.FindMessage("if", &conditions) == B_OK) {
+ Condition* condition =
Conditions::FromMessage(conditions);
+ if (condition != NULL) {
+ pass = condition->Test(*this);
+ debug_printf("Test: %s -> %d\n",
condition->ToString().String(),
+ pass);
+ delete condition;
+ } else
+ debug_printf("Could not parse condition!\n");
+ }
+
+ if (pass) {
+ _AddRunTargets(runMessage, NULL);
+ _AddRunTargets(runMessage, "then");
+ } else {
+ _AddRunTargets(runMessage, "else");
+ }
+ }
+}
+
+
+void
+LaunchDaemon::_AddRunTargets(BMessage& message, const char* name)
+{
+ BMessage targets;
+ if (name != NULL && message.FindMessage(name, &targets) != B_OK)
+ return;
+
+ const char* target;
+ for (int32 index = 0; targets.FindString("target", index, &target) ==
B_OK;
+ index++) {
+ fRunTargets.Add(target);
+ }
+}
+
+
+void
LaunchDaemon::_AddJob(Target* target, bool service, BMessage& message)
{
BString name = message.GetString("name");
diff --git a/src/servers/launch/SettingsParser.cpp
b/src/servers/launch/SettingsParser.cpp
index 1df5f35..083993d 100644
--- a/src/servers/launch/SettingsParser.cpp
+++ b/src/servers/launch/SettingsParser.cpp
@@ -74,6 +74,29 @@ private:
};


+class RunConverter : public DriverSettingsConverter {
+public:
+ status_t ConvertFromDriverSettings(const driver_parameter& parameter,
+ const char* name, int32 index, uint32 type, BMessage& target)
+ {
+ if (parameter.parameter_count == 0)
+ return target.AddString("target",
parameter.values[index]);
+
+ return B_NOT_SUPPORTED;
+ }
+
+ status_t ConvertEmptyFromDriverSettings(
+ const driver_parameter& parameter, const char* name, uint32
type,
+ BMessage& target)
+ {
+ if (parameter.parameter_count != 0)
+ return B_OK;
+
+ return target.AddString("target", name);
+ }
+};
+
+
const static settings_template kConditionTemplate[] = {
{B_STRING_TYPE, NULL, NULL, true, new ConditionConverter()},
{B_MESSAGE_TYPE, "not", kConditionTemplate},
@@ -108,10 +131,24 @@ const static settings_template kTargetTemplate[] = {
{0, NULL, NULL}
};

+const static settings_template kRunConditionalTemplate[] = {
+ {B_STRING_TYPE, NULL, NULL, true, new RunConverter()},
+ {0, NULL, NULL}
+};
+
+const static settings_template kRunTemplate[] = {
+ {B_STRING_TYPE, NULL, NULL, true, new RunConverter()},
+ {B_MESSAGE_TYPE, "if", kConditionTemplate},
+ {B_MESSAGE_TYPE, "then", kRunConditionalTemplate},
+ {B_MESSAGE_TYPE, "else", kRunConditionalTemplate},
+ {0, NULL, NULL}
+};
+
const static settings_template kSettingsTemplate[] = {
{B_MESSAGE_TYPE, "target", kTargetTemplate},
{B_MESSAGE_TYPE, "job", kJobTemplate},
{B_MESSAGE_TYPE, "service", kJobTemplate},
+ {B_MESSAGE_TYPE, "run", kRunTemplate},
{0, NULL, NULL}
};

diff --git a/src/tests/servers/launch/SettingsParserTest.cpp
b/src/tests/servers/launch/SettingsParserTest.cpp
index f081fdc..add04b9 100644
--- a/src/tests/servers/launch/SettingsParserTest.cpp
+++ b/src/tests/servers/launch/SettingsParserTest.cpp
@@ -153,7 +153,8 @@ SettingsParserTest::TestConditionsMultiLineFlatNotWithArgs()
BString(args.GetString("args", 0, "-")));
CPPUNIT_ASSERT_EQUAL(BString("two"),
BString(args.GetString("args", 1, "-")));
- CPPUNIT_ASSERT_EQUAL(2, args.CountNames(B_ANY_TYPE));
+ CPPUNIT_ASSERT_EQUAL(1, args.CountNames(B_ANY_TYPE));
+ CPPUNIT_ASSERT_EQUAL(2, _ArrayCount(args, "args"));
}


@@ -177,11 +178,122 @@ SettingsParserTest::TestConditionsMultiLineNot()
}


+void
+SettingsParserTest::TestRunFlat()
+{
+ SettingsParser parser;
+ BMessage jobs;
+ CPPUNIT_ASSERT_EQUAL(B_OK, parser.Parse("run me", jobs));
+ CPPUNIT_ASSERT_EQUAL(1, jobs.CountNames(B_ANY_TYPE));
+
+ BMessage message;
+ CPPUNIT_ASSERT_EQUAL(B_OK, jobs.FindMessage("run", &message));
+ CPPUNIT_ASSERT_EQUAL(BString("me"),
+ BString(message.GetString("target", "-")));
+ CPPUNIT_ASSERT_EQUAL(1, _ArrayCount(message, "target"));
+ CPPUNIT_ASSERT_EQUAL(1, message.CountNames(B_ANY_TYPE));
+}
+
+
+void
+SettingsParserTest::TestRunMultiLine()
+{
+ SettingsParser parser;
+ BMessage jobs;
+ status_t status = parser.Parse("run {\n"
+ "\tme\n"
+ "\tyou\n"
+ "}\n", jobs);
+ CPPUNIT_ASSERT_EQUAL(B_OK, status);
+ CPPUNIT_ASSERT_EQUAL(1, jobs.CountNames(B_ANY_TYPE));
+
+ BMessage message;
+ CPPUNIT_ASSERT_EQUAL(B_OK, jobs.FindMessage("run", &message));
+ CPPUNIT_ASSERT_EQUAL(BString("me"),
+ BString(message.GetString("target", 0, "-")));
+ CPPUNIT_ASSERT_EQUAL(BString("you"),
+ BString(message.GetString("target", 1, "-")));
+ CPPUNIT_ASSERT_EQUAL(2, _ArrayCount(message, "target"));
+ CPPUNIT_ASSERT_EQUAL(1, message.CountNames(B_ANY_TYPE));
+}
+
+
+void
+SettingsParserTest::TestRunIfThenElseFlat()
+{
+ SettingsParser parser;
+ BMessage jobs;
+ status_t status = parser.Parse("run {\n"
+ "\tif safemode\n"
+ "\tthen this\n"
+ "\telse that\n"
+ "}\n", jobs);
+ CPPUNIT_ASSERT_EQUAL(B_OK, status);
+
+ BMessage message;
+ CPPUNIT_ASSERT_EQUAL(B_OK, jobs.FindMessage("run", &message));
+ CPPUNIT_ASSERT_EQUAL(3, message.CountNames(B_ANY_TYPE));
+
+ BMessage then;
+ CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("then", &then));
+ CPPUNIT_ASSERT_EQUAL(BString("this"),
+ BString(then.GetString("target", "-")));
+ CPPUNIT_ASSERT_EQUAL(1, _ArrayCount(then, "target"));
+ CPPUNIT_ASSERT_EQUAL(1, then.CountNames(B_ANY_TYPE));
+
+ BMessage otherwise;
+ CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("else", &otherwise));
+ CPPUNIT_ASSERT_EQUAL(BString("that"),
+ BString(otherwise.GetString("target", "-")));
+ CPPUNIT_ASSERT_EQUAL(1, _ArrayCount(otherwise, "target"));
+ CPPUNIT_ASSERT_EQUAL(1, otherwise.CountNames(B_ANY_TYPE));
+}
+
+
+void
+SettingsParserTest::TestRunIfThenElseMultiLine()
+{
+ SettingsParser parser;
+ BMessage jobs;
+ status_t status = parser.Parse("run {\n"
+ "\tif {\n"
+ "\t\tread_only\n"
+ "\t}\n"
+ "\tthen {\n"
+ "\t\tthis\n"
+ "\t}\n"
+ "\telse {\n"
+ "\t\tthat\n"
+ "\t}\n"
+ "}\n", jobs);
+ CPPUNIT_ASSERT_EQUAL(B_OK, status);
+
+ BMessage message;
+ CPPUNIT_ASSERT_EQUAL(B_OK, jobs.FindMessage("run", &message));
+ CPPUNIT_ASSERT_EQUAL(3, message.CountNames(B_ANY_TYPE));
+
+ BMessage then;
+ CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("then", &then));
+ CPPUNIT_ASSERT_EQUAL(BString("this"),
+ BString(then.GetString("target", "-")));
+ CPPUNIT_ASSERT_EQUAL(1, _ArrayCount(then, "target"));
+ CPPUNIT_ASSERT_EQUAL(1, then.CountNames(B_ANY_TYPE));
+
+ BMessage otherwise;
+ CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("else", &otherwise));
+ CPPUNIT_ASSERT_EQUAL(BString("that"),
+ BString(otherwise.GetString("target", "-")));
+ CPPUNIT_ASSERT_EQUAL(1, _ArrayCount(otherwise, "target"));
+ CPPUNIT_ASSERT_EQUAL(1, otherwise.CountNames(B_ANY_TYPE));
+}
+
+
/*static*/ void
SettingsParserTest::AddTests(BTestSuite& parent)
{
CppUnit::TestSuite& suite = *new
CppUnit::TestSuite("SettingsParserTest");

+ // Conditions
suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
"SettingsParserTest::TestConditionsMultiLine",
&SettingsParserTest::TestConditionsMultiLine));
@@ -207,6 +319,20 @@ SettingsParserTest::AddTests(BTestSuite& parent)
"SettingsParserTest::TestConditionsMultiLineNot",
&SettingsParserTest::TestConditionsMultiLineNot));

+ // Run
+ suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
+ "SettingsParserTest::TestRunFlat",
+ &SettingsParserTest::TestRunFlat));
+ suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
+ "SettingsParserTest::TestRunMultiLine",
+ &SettingsParserTest::TestRunMultiLine));
+ suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
+ "SettingsParserTest::TestRunIfThenElseFlat",
+ &SettingsParserTest::TestRunIfThenElseFlat));
+ suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
+ "SettingsParserTest::TestRunIfThenElseMultiLine",
+ &SettingsParserTest::TestRunIfThenElseMultiLine));
+
parent.addTest("SettingsParserTest", &suite);
}

@@ -233,3 +359,14 @@ SettingsParserTest::_ParseCondition(const char* text,
BMessage& message)

return job.FindMessage("if", &message);
}
+
+
+int32
+SettingsParserTest::_ArrayCount(BMessage& message, const char* name)
+{
+ int32 found;
+ if (message.GetInfo(name, NULL, &found, NULL) != B_OK)
+ return 0;
+
+ return found;
+}
diff --git a/src/tests/servers/launch/SettingsParserTest.h
b/src/tests/servers/launch/SettingsParserTest.h
index bd99269..d9ffa39 100644
--- a/src/tests/servers/launch/SettingsParserTest.h
+++ b/src/tests/servers/launch/SettingsParserTest.h
@@ -26,11 +26,18 @@ public:
void
TestConditionsMultiLineFlatNotWithArgs();
void
TestConditionsMultiLineNot();

+ void TestRunFlat();
+ void TestRunMultiLine();
+ void TestRunIfThenElseFlat();
+ void
TestRunIfThenElseMultiLine();
+
static void AddTests(BTestSuite& suite);

private:
status_t _ParseCondition(const
char* text,

BMessage& message);
+ int32 _ArrayCount(BMessage&
message,
+ const
char* name);
};




Other related posts:

  • » [haiku-commits] BRANCH axeld-github.launch_daemon [196b0c640f67] src/tests/servers/launch src/servers/launch data/launch - axeld-github . launch_daemon