launch_daemon: Started working on condition parsing.
* Moved related test code from DriverSettingsMessageAdapterTest to the SettingsParser class. * Added SettingsParserTest class -- most tests already succeed, but not all; support for the flattened "not" is not working yet.
This commit is contained in:
@@ -9,6 +9,65 @@
|
||||
#include <DriverSettingsMessageAdapter.h>
|
||||
|
||||
|
||||
class ConditionConverter : public DriverSettingsConverter {
|
||||
public:
|
||||
status_t ConvertFromDriverSettings(const driver_parameter& parameter,
|
||||
const char* name, int32 index, uint32 type, BMessage& target)
|
||||
{
|
||||
BMessage message;
|
||||
if (strcmp(parameter.name, "if") == 0) {
|
||||
// Parse values directly following "if", with special
|
||||
// handling for the "not" operator.
|
||||
if (index != 0)
|
||||
return B_OK;
|
||||
|
||||
BMessage* add = ⌖
|
||||
bool not = parameter.value_count > 1
|
||||
&& strcmp(parameter.values[0], "not") == 0;
|
||||
if (not) {
|
||||
add = &message;
|
||||
index++;
|
||||
}
|
||||
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;
|
||||
}
|
||||
status_t status = add->AddMessage(condition, &args);
|
||||
if (status == B_OK && not)
|
||||
status = target.AddMessage("not", &message);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (parameter.parameter_count != 0)
|
||||
return B_OK;
|
||||
|
||||
BMessage message;
|
||||
return target.AddMessage(name, &message);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const static settings_template kConditionTemplate[] = {
|
||||
{B_STRING_TYPE, NULL, NULL, true, new ConditionConverter()},
|
||||
{B_MESSAGE_TYPE, "not", kConditionTemplate},
|
||||
{B_MESSAGE_TYPE, "and", kConditionTemplate},
|
||||
{B_MESSAGE_TYPE, "or", kConditionTemplate},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
const static settings_template kPortTemplate[] = {
|
||||
{B_STRING_TYPE, "name", NULL, true},
|
||||
{B_INT32_TYPE, "capacity", NULL},
|
||||
@@ -21,18 +80,11 @@ const static settings_template kJobTemplate[] = {
|
||||
{B_STRING_TYPE, "requires", NULL},
|
||||
{B_BOOL_TYPE, "legacy", NULL},
|
||||
{B_MESSAGE_TYPE, "port", kPortTemplate},
|
||||
{B_MESSAGE_TYPE, "if", kConditionTemplate},
|
||||
{B_BOOL_TYPE, "no_safemode", NULL},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
const static settings_template kConditionTemplate[] = {
|
||||
{B_STRING_TYPE, NULL, NULL, true},
|
||||
{B_MESSAGE_TYPE, "not", kConditionTemplate},
|
||||
{B_MESSAGE_TYPE, "and", kConditionTemplate},
|
||||
{B_MESSAGE_TYPE, "or", kConditionTemplate},
|
||||
{0, NULL, NULL}
|
||||
};
|
||||
|
||||
const static settings_template kTargetTemplate[] = {
|
||||
{B_STRING_TYPE, "name", NULL, true},
|
||||
{B_BOOL_TYPE, "reset", NULL},
|
||||
@@ -61,3 +113,25 @@ SettingsParser::ParseFile(const char* path, BMessage& settings)
|
||||
DriverSettingsMessageAdapter adapter;
|
||||
return adapter.ConvertFromDriverSettings(path, kSettingsTemplate, settings);
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST_HAIKU
|
||||
|
||||
|
||||
status_t
|
||||
SettingsParser::Parse(const char* text, BMessage& settings)
|
||||
{
|
||||
void* driverSettings = parse_driver_settings_string(text);
|
||||
if (driverSettings == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
DriverSettingsMessageAdapter adapter;
|
||||
status_t status = adapter.ConvertFromDriverSettings(
|
||||
*get_driver_settings(driverSettings), kSettingsTemplate, settings);
|
||||
|
||||
delete_driver_settings(driverSettings);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
#endif // TEST_HAIKU
|
||||
|
||||
@@ -14,6 +14,10 @@ public:
|
||||
SettingsParser();
|
||||
|
||||
status_t ParseFile(const char* path, BMessage& settings);
|
||||
|
||||
#ifdef TEST_HAIKU
|
||||
status_t Parse(const char* text, BMessage& settings);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -325,55 +325,6 @@ DriverSettingsMessageAdapterTest::TestWildcard()
|
||||
CPPUNIT_ASSERT_EQUAL(BString("works"),
|
||||
BString(subMessage.GetString("still", "-")));
|
||||
CPPUNIT_ASSERT_EQUAL(1, subMessage.CountNames(B_ANY_TYPE));
|
||||
|
||||
class WildcardConverter : public DriverSettingsConverter {
|
||||
public:
|
||||
status_t ConvertFromDriverSettings(const driver_parameter& parameter,
|
||||
const char* name, int32 index, uint32 type, BMessage& target)
|
||||
{
|
||||
BMessage message;
|
||||
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)
|
||||
{
|
||||
if (parameter.parameter_count != 0)
|
||||
return B_OK;
|
||||
|
||||
BMessage message;
|
||||
return target.AddMessage(name, &message);
|
||||
}
|
||||
} converter;
|
||||
|
||||
const settings_template kSubTemplateC[] = {
|
||||
{B_STRING_TYPE, NULL, NULL, true, &converter},
|
||||
{}
|
||||
};
|
||||
const settings_template kTemplateC[] = {
|
||||
{B_MESSAGE_TYPE, "if", kSubTemplateC},
|
||||
{}
|
||||
};
|
||||
|
||||
Settings settingsD("if {\n"
|
||||
"\tsafemode\n"
|
||||
"\tfile_exists one\n"
|
||||
"}\n");
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, settingsD.ToMessage(kTemplateC, message));
|
||||
CPPUNIT_ASSERT_EQUAL(1, message.CountNames(B_ANY_TYPE));
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("if", &subMessage));
|
||||
CPPUNIT_ASSERT_EQUAL(2, subMessage.CountNames(B_ANY_TYPE));
|
||||
BMessage subSubMessage;
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, subMessage.FindMessage("safemode",
|
||||
&subSubMessage));
|
||||
CPPUNIT_ASSERT(subSubMessage.IsEmpty());
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, subMessage.FindMessage("file_exists",
|
||||
&subSubMessage));
|
||||
CPPUNIT_ASSERT_EQUAL(BString("one"),
|
||||
BString(subSubMessage.GetString("args", 0, "-")));
|
||||
CPPUNIT_ASSERT_EQUAL(1, subSubMessage.CountNames(B_ANY_TYPE));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,4 +3,5 @@ SubDir HAIKU_TOP src tests servers ;
|
||||
SubInclude HAIKU_TOP src tests servers app ;
|
||||
SubInclude HAIKU_TOP src tests servers debug ;
|
||||
SubInclude HAIKU_TOP src tests servers input ;
|
||||
SubInclude HAIKU_TOP src tests servers launch ;
|
||||
SubInclude HAIKU_TOP src tests servers registrar ;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
SubDir HAIKU_TOP src tests servers launch ;
|
||||
|
||||
AddSubDirSupportedPlatforms libbe_test ;
|
||||
|
||||
UsePrivateHeaders app shared support ;
|
||||
|
||||
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src servers launch ] ;
|
||||
|
||||
UnitTestLib liblaunch_daemontest.so :
|
||||
LaunchDaemonTestAddon.cpp
|
||||
|
||||
SettingsParserTest.cpp
|
||||
SettingsParser.cpp
|
||||
|
||||
: be libshared.a [ TargetLibstdc++ ] [ TargetLibsupc++ ]
|
||||
;
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2015, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <TestSuite.h>
|
||||
#include <TestSuiteAddon.h>
|
||||
|
||||
#include "SettingsParserTest.h"
|
||||
|
||||
|
||||
BTestSuite*
|
||||
getTestSuite()
|
||||
{
|
||||
BTestSuite* suite = new BTestSuite("LaunchDaemon");
|
||||
|
||||
SettingsParserTest::AddTests(*suite);
|
||||
|
||||
return suite;
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright 2015, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "SettingsParserTest.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <driver_settings.h>
|
||||
#include <String.h>
|
||||
|
||||
#include <cppunit/TestCaller.h>
|
||||
#include <cppunit/TestSuite.h>
|
||||
|
||||
#include "SettingsParser.h"
|
||||
|
||||
|
||||
SettingsParserTest::SettingsParserTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
SettingsParserTest::~SettingsParserTest()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsParserTest::TestConditionsMultiLine()
|
||||
{
|
||||
BMessage message;
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, _ParseCondition("if {\n"
|
||||
"\tsafemode\n"
|
||||
"\tfile_exists one\n"
|
||||
"}\n", message));
|
||||
CPPUNIT_ASSERT_EQUAL(2, message.CountNames(B_ANY_TYPE));
|
||||
|
||||
BMessage subMessage;
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("safemode", &subMessage));
|
||||
CPPUNIT_ASSERT(subMessage.IsEmpty());
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("file_exists",
|
||||
&subMessage));
|
||||
CPPUNIT_ASSERT_EQUAL(BString("one"),
|
||||
BString(subMessage.GetString("args", 0, "-")));
|
||||
CPPUNIT_ASSERT_EQUAL(1, subMessage.CountNames(B_ANY_TYPE));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsParserTest::TestConditionsFlat()
|
||||
{
|
||||
BMessage message;
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, _ParseCondition("if safemode\n", message));
|
||||
CPPUNIT_ASSERT_EQUAL(1, message.CountNames(B_ANY_TYPE));
|
||||
|
||||
BMessage args;
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("safemode", &args));
|
||||
CPPUNIT_ASSERT(args.IsEmpty());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsParserTest::TestConditionsFlatWithNot()
|
||||
{
|
||||
BMessage message;
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, _ParseCondition("if not safemode\n", message));
|
||||
CPPUNIT_ASSERT_EQUAL(1, message.CountNames(B_ANY_TYPE));
|
||||
|
||||
BMessage subMessage;
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("not",
|
||||
&subMessage));
|
||||
|
||||
BMessage args;
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, subMessage.FindMessage("safemode", &args));
|
||||
CPPUNIT_ASSERT(args.IsEmpty());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsParserTest::TestConditionsFlatWithArgs()
|
||||
{
|
||||
BMessage message;
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK,
|
||||
_ParseCondition("if file_exists one\n", message));
|
||||
CPPUNIT_ASSERT_EQUAL(1, message.CountNames(B_ANY_TYPE));
|
||||
|
||||
BMessage args;
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("file_exists", &args));
|
||||
CPPUNIT_ASSERT_EQUAL(BString("one"),
|
||||
BString(args.GetString("args", 0, "-")));
|
||||
CPPUNIT_ASSERT_EQUAL(1, args.CountNames(B_ANY_TYPE));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsParserTest::TestConditionsFlatWithNotAndArgs()
|
||||
{
|
||||
BMessage message;
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK,
|
||||
_ParseCondition("if not file_exists one\n", message));
|
||||
CPPUNIT_ASSERT_EQUAL(1, message.CountNames(B_ANY_TYPE));
|
||||
|
||||
BMessage subMessage;
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("not",
|
||||
&subMessage));
|
||||
|
||||
BMessage args;
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, subMessage.FindMessage("file_exists", &args));
|
||||
CPPUNIT_ASSERT_EQUAL(BString("one"),
|
||||
BString(args.GetString("args", 0, "-")));
|
||||
CPPUNIT_ASSERT_EQUAL(1, args.CountNames(B_ANY_TYPE));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsParserTest::TestConditionsMultiLineFlatNot()
|
||||
{
|
||||
BMessage message;
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, _ParseCondition("if {\n"
|
||||
"\tnot safemode\n"
|
||||
"}\n", message));
|
||||
message.PrintToStream();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsParserTest::TestConditionsMultiLineFlatNotWithArgs()
|
||||
{
|
||||
BMessage message;
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, _ParseCondition("if {\n"
|
||||
"\tnot file_exists one\n"
|
||||
"}\n", message));
|
||||
message.PrintToStream();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsParserTest::TestConditionsMultiLineNot()
|
||||
{
|
||||
BMessage message;
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, _ParseCondition("if {\n"
|
||||
"\tnot {\n"
|
||||
"\t\tsafemode\n"
|
||||
"\t}\n"
|
||||
"}\n", message));
|
||||
|
||||
BMessage subMessage;
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("not", &subMessage));
|
||||
|
||||
BMessage args;
|
||||
CPPUNIT_ASSERT_EQUAL(B_OK, subMessage.FindMessage("safemode", &args));
|
||||
CPPUNIT_ASSERT(args.IsEmpty());
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*static*/ void
|
||||
SettingsParserTest::AddTests(BTestSuite& parent)
|
||||
{
|
||||
CppUnit::TestSuite& suite = *new CppUnit::TestSuite("SettingsParserTest");
|
||||
|
||||
suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
|
||||
"SettingsParserTest::TestConditionsMultiLine",
|
||||
&SettingsParserTest::TestConditionsMultiLine));
|
||||
suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
|
||||
"SettingsParserTest::TestConditionsFlat",
|
||||
&SettingsParserTest::TestConditionsFlat));
|
||||
suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
|
||||
"SettingsParserTest::TestConditionsFlatWithNot",
|
||||
&SettingsParserTest::TestConditionsFlatWithNot));
|
||||
suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
|
||||
"SettingsParserTest::TestConditionsFlatWithArgs",
|
||||
&SettingsParserTest::TestConditionsFlatWithArgs));
|
||||
suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
|
||||
"SettingsParserTest::TestConditionsFlatWithNotAndArgs",
|
||||
&SettingsParserTest::TestConditionsFlatWithNotAndArgs));
|
||||
suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
|
||||
"SettingsParserTest::TestConditionsMultiLineFlatNot",
|
||||
&SettingsParserTest::TestConditionsMultiLineFlatNot));
|
||||
suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
|
||||
"SettingsParserTest::TestConditionsMultiLineFlatNotWithArgs",
|
||||
&SettingsParserTest::TestConditionsMultiLineFlatNotWithArgs));
|
||||
suite.addTest(new CppUnit::TestCaller<SettingsParserTest>(
|
||||
"SettingsParserTest::TestConditionsMultiLineNot",
|
||||
&SettingsParserTest::TestConditionsMultiLineNot));
|
||||
|
||||
parent.addTest("SettingsParserTest", &suite);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
SettingsParserTest::_ParseCondition(const char* text, BMessage& message)
|
||||
{
|
||||
SettingsParser parser;
|
||||
BString input("job A {\n");
|
||||
input << text << "\n}\n";
|
||||
|
||||
BMessage jobs;
|
||||
status_t status = parser.Parse(input, jobs);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
BMessage job;
|
||||
status = jobs.FindMessage("job", 0, &job);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(2, job.CountNames(B_ANY_TYPE));
|
||||
CPPUNIT_ASSERT_EQUAL(BString("A"), BString(job.GetString("name")));
|
||||
|
||||
return job.FindMessage("if", &message);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2015, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef SETTINGS_PARSER_TEST_H
|
||||
#define SETTINGS_PARSER_TEST_H
|
||||
|
||||
|
||||
#include <TestCase.h>
|
||||
#include <TestSuite.h>
|
||||
|
||||
#include <Message.h>
|
||||
|
||||
|
||||
class SettingsParserTest : public CppUnit::TestCase {
|
||||
public:
|
||||
SettingsParserTest();
|
||||
virtual ~SettingsParserTest();
|
||||
|
||||
void TestConditionsMultiLine();
|
||||
void TestConditionsFlat();
|
||||
void TestConditionsFlatWithNot();
|
||||
void TestConditionsFlatWithArgs();
|
||||
void TestConditionsFlatWithNotAndArgs();
|
||||
void TestConditionsMultiLineFlatNot();
|
||||
void TestConditionsMultiLineFlatNotWithArgs();
|
||||
void TestConditionsMultiLineNot();
|
||||
|
||||
static void AddTests(BTestSuite& suite);
|
||||
|
||||
private:
|
||||
status_t _ParseCondition(const char* text,
|
||||
BMessage& message);
|
||||
};
|
||||
|
||||
|
||||
#endif // SETTINGS_PARSER_TEST_H
|
||||
Reference in New Issue
Block a user