⛏️ index : haiku.git

/*
 * Copyright 2015, Axel Dörfler, axeld@pinc-software.de.
 * Distributed under the terms of the MIT License.
 */


#include "DriverSettingsMessageAdapterTest.h"

#include <stdlib.h>

#include <driver_settings.h>
#include <String.h>

#include <DriverSettingsMessageAdapter.h>

#include <cppunit/TestCaller.h>
#include <cppunit/TestSuite.h>


namespace {


class Settings {
public:
	Settings(const char* string)
	{
		fSettings = parse_driver_settings_string(string);
		CppUnit::Asserter::failIf(fSettings == NULL,
			"Could not parse settings");
	}

	status_t ToMessage(const settings_template* settingsTemplate,
		BMessage& message)
	{
		DriverSettingsMessageAdapter adapter;
		return adapter.ConvertFromDriverSettings(
			*get_driver_settings(fSettings), settingsTemplate, message);
	}

	~Settings()
	{
		unload_driver_settings(fSettings);
	}

private:
	void* fSettings;
};


}	// empty namespace


// #pragma mark -


DriverSettingsMessageAdapterTest::DriverSettingsMessageAdapterTest()
{
}


DriverSettingsMessageAdapterTest::~DriverSettingsMessageAdapterTest()
{
}


void
DriverSettingsMessageAdapterTest::TestPrimitivesToMessage()
{
	const settings_template kTemplate[] = {
		{B_BOOL_TYPE, "bool1", NULL},
		{B_BOOL_TYPE, "bool2", NULL},
		{B_BOOL_TYPE, "bool3", NULL},
		{B_BOOL_TYPE, "bool4", NULL},
		{B_BOOL_TYPE, "bool5", NULL},
		{B_BOOL_TYPE, "bool6", NULL},
		{B_BOOL_TYPE, "bool7", NULL},
		{B_BOOL_TYPE, "bool8", NULL},
		{B_BOOL_TYPE, "bool9", NULL},
		{B_BOOL_TYPE, "empty_bool", NULL},
		{B_INT32_TYPE, "int32", NULL},
		{B_INT32_TYPE, "negative_int32", NULL},
		{B_INT32_TYPE, "empty_int32", NULL},
		{B_STRING_TYPE, "string", NULL},
		{B_STRING_TYPE, "long_string", NULL},
		{B_STRING_TYPE, "empty_string", NULL},
		{}
	};
	Settings settings("bool1 true\n"
		"bool2 1\n"
		"bool3 on\n"
		"bool4 yes\n"
		"bool5 enabled\n"
		"bool6 false\n"
		"bool7 off\n"
		"bool8 gurkensalat\n"
		"bool9 0\n"
		"empty_bool\n"
		"int32 42\n"
		"negative_int32 -42\n"
		"empty_int32\n"
		"string Hey\n"
		"long_string \"This is but a test\"\n"
		"empty_string\n");

	BMessage message;
	CPPUNIT_ASSERT_EQUAL(B_OK, settings.ToMessage(kTemplate, message));
	CPPUNIT_ASSERT_EQUAL(10, message.CountNames(B_BOOL_TYPE));
	CPPUNIT_ASSERT_EQUAL(2, message.CountNames(B_INT32_TYPE));
	CPPUNIT_ASSERT_EQUAL(2, message.CountNames(B_STRING_TYPE));
	CPPUNIT_ASSERT_EQUAL(14, message.CountNames(B_ANY_TYPE));

	// bool values
	CPPUNIT_ASSERT_EQUAL_MESSAGE("bool1", true, message.GetBool("bool1"));
	CPPUNIT_ASSERT_EQUAL_MESSAGE("bool2", true, message.GetBool("bool2"));
	CPPUNIT_ASSERT_EQUAL_MESSAGE("bool3", true, message.GetBool("bool3"));
	CPPUNIT_ASSERT_EQUAL_MESSAGE("bool4", true, message.GetBool("bool4"));
	CPPUNIT_ASSERT_EQUAL_MESSAGE("bool5", true, message.GetBool("bool5"));
	CPPUNIT_ASSERT_EQUAL_MESSAGE("bool6", false,
		message.GetBool("bool6", true));
	CPPUNIT_ASSERT_EQUAL_MESSAGE("bool7", false,
		message.GetBool("bool7", true));
	CPPUNIT_ASSERT_EQUAL_MESSAGE("bool8", false,
		message.GetBool("bool8", true));
	CPPUNIT_ASSERT_EQUAL_MESSAGE("bool9", false,
		message.GetBool("bool9", true));
	CPPUNIT_ASSERT_EQUAL_MESSAGE("empty_bool", true,
		message.GetBool("empty_bool"));

	// int32 values
	CPPUNIT_ASSERT_EQUAL(42, message.GetInt32("int32", 0));
	CPPUNIT_ASSERT_EQUAL(-42, message.GetInt32("negative_int32", 0));
	CPPUNIT_ASSERT_EQUAL(false, message.HasInt32("empty_int32"));

	// string values
	CPPUNIT_ASSERT_EQUAL(BString("Hey"), BString(message.GetString("string")));
	CPPUNIT_ASSERT_EQUAL(BString("This is but a test"),
		BString(message.GetString("long_string")));
	CPPUNIT_ASSERT_EQUAL(false, message.HasString("empty_string"));
}


void
DriverSettingsMessageAdapterTest::TestMessage()
{
	const settings_template kSubTemplate[] = {
		{B_BOOL_TYPE, "bool", NULL},
		{}
	};
	const settings_template kTemplate[] = {
		{B_MESSAGE_TYPE, "message", kSubTemplate},
		{}
	};
	Settings settingsA("message {\n"
		"    bool\n"
		"}\n");
	BMessage message;
	CPPUNIT_ASSERT_EQUAL(B_OK, settingsA.ToMessage(kTemplate, message));
	BMessage subMessage;
	CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("message", &subMessage));
	CPPUNIT_ASSERT_EQUAL_MESSAGE("bool", true, subMessage.GetBool("bool"));
	CPPUNIT_ASSERT_EQUAL(1, message.CountNames(B_ANY_TYPE));

	Settings settingsB("message {\n"
		"}\n");
	CPPUNIT_ASSERT_EQUAL(B_OK, settingsB.ToMessage(kTemplate, message));
	CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("message", &subMessage));
	CPPUNIT_ASSERT_EQUAL(1, message.CountNames(B_ANY_TYPE));

	Settings settingsC("\n");
	CPPUNIT_ASSERT_EQUAL(B_OK, settingsC.ToMessage(kTemplate, message));
	CPPUNIT_ASSERT(message.IsEmpty());
}


void
DriverSettingsMessageAdapterTest::TestParent()
{
	const settings_template kSubTemplate[] = {
		{B_STRING_TYPE, "name", NULL, true},
		{B_BOOL_TYPE, "bool", NULL},
		{}
	};
	const settings_template kTemplate[] = {
		{B_MESSAGE_TYPE, "message", kSubTemplate},
		{}
	};
	Settings settingsA("message first {\n"
		"    bool\n"
		"}\n");
	BMessage message;
	CPPUNIT_ASSERT_EQUAL(B_OK, settingsA.ToMessage(kTemplate, message));
	BMessage subMessage;
	CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("message", &subMessage));
	CPPUNIT_ASSERT_EQUAL_MESSAGE("bool", true, subMessage.GetBool("bool"));
	CPPUNIT_ASSERT_EQUAL(BString("first"),
		BString(subMessage.GetString("name")));

	Settings settingsB("message second\n");
	CPPUNIT_ASSERT_EQUAL(B_OK, settingsB.ToMessage(kTemplate, message));
	CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("message", &subMessage));
	CPPUNIT_ASSERT_EQUAL(false, subMessage.HasBool("bool"));
	CPPUNIT_ASSERT_EQUAL(BString("second"),
		BString(subMessage.GetString("name", "-/-")));

	const settings_template kSubSubTemplateC[] = {
		{B_STRING_TYPE, "subname", NULL, true},
		{B_BOOL_TYPE, "bool", NULL},
		{}
	};
	const settings_template kSubTemplateC[] = {
		{B_STRING_TYPE, "name", NULL, true},
		{B_MESSAGE_TYPE, "sub", kSubSubTemplateC},
		{}
	};
	const settings_template kTemplateC[] = {
		{B_MESSAGE_TYPE, "message", kSubTemplateC},
		{}
	};

	Settings settingsC("message other {\n"
		"    sub third {\n"
		"        hun audo\n"
		"    }\n"
		"    sub fourth\n"
		"}");
	CPPUNIT_ASSERT_EQUAL(B_OK, settingsC.ToMessage(kTemplateC, message));
	CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("message", &subMessage));
	CPPUNIT_ASSERT_EQUAL(false, subMessage.HasBool("bool"));
	CPPUNIT_ASSERT_EQUAL(BString("other"),
		BString(subMessage.GetString("name", "-/-")));
}


void
DriverSettingsMessageAdapterTest::TestConverter()
{
	class HexConverter : public DriverSettingsConverter {
	public:
		status_t ConvertFromDriverSettings(const driver_parameter& parameter,
			const char* name, int32 index, uint32 type, BMessage& target)
		{
			const char* value = parameter.values[index];
			if (value[0] == '0' && value[1] == 'x')
				return target.AddInt32(name, (int32)strtol(value, NULL, 0));
			return B_NOT_SUPPORTED;
		}

		status_t ConvertToDriverSettings(const BMessage& source,
			const char* name, int32 index, uint32 type, BString& value)
		{
			int32 intValue;
			if (index == 0 && source.FindInt32(name, 0, &intValue) == B_OK) {
				BString string;
				string.SetToFormat("0x%" B_PRIu32, intValue);
				value << string;

				return B_OK;
			}
			return B_NOT_SUPPORTED;
		}
	} converter;

	const settings_template kTemplate[] = {
		{B_INT32_TYPE, "test", NULL, false, &converter},
		{}
	};

	Settings settings("test 0x2a 43");
	BMessage message;
	CPPUNIT_ASSERT_EQUAL(B_OK, settings.ToMessage(kTemplate, message));
	CPPUNIT_ASSERT_EQUAL(42, message.GetInt32("test", 0, 0));
	CPPUNIT_ASSERT_EQUAL(43, message.GetInt32("test", 1, 0));
	CPPUNIT_ASSERT_EQUAL(1, message.CountNames(B_ANY_TYPE));
}


void
DriverSettingsMessageAdapterTest::TestWildcard()
{
	const settings_template kTemplateA[] = {
		{B_STRING_TYPE, NULL, NULL},
		{B_INT32_TYPE, "test", NULL},
		{}
	};

	Settings settingsA("this is\n"
		"just a\n"
		"test 42 43");
	BMessage message;
	CPPUNIT_ASSERT_EQUAL(B_OK, settingsA.ToMessage(kTemplateA, message));
	CPPUNIT_ASSERT_EQUAL(42, message.GetInt32("test", 0, 0));
	CPPUNIT_ASSERT_EQUAL(43, message.GetInt32("test", 1, 0));
	CPPUNIT_ASSERT_EQUAL(3, message.CountNames(B_ANY_TYPE));
	CPPUNIT_ASSERT_EQUAL(BString("is"),
		BString(message.GetString("this", "-")));
	CPPUNIT_ASSERT_EQUAL(BString("a"),
		BString(message.GetString("just", "-")));

	const settings_template kSubTemplateB[] = {
		{B_STRING_TYPE, NULL, NULL, true},
		{}
	};
	const settings_template kTemplateB[] = {
		{B_MESSAGE_TYPE, "it", kSubTemplateB},
		{}
	};

	Settings settingsB("it just works\n");
	CPPUNIT_ASSERT_EQUAL(B_OK, settingsB.ToMessage(kTemplateB, message));
	CPPUNIT_ASSERT_EQUAL(1, message.CountNames(B_ANY_TYPE));
	BMessage subMessage;
	CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("it", &subMessage));
	CPPUNIT_ASSERT_EQUAL(BString("just"),
		BString(subMessage.GetString("it", 0, "-")));
	CPPUNIT_ASSERT_EQUAL(BString("works"),
		BString(subMessage.GetString("it", 1, "-")));
	CPPUNIT_ASSERT_EQUAL(1, subMessage.CountNames(B_ANY_TYPE));

	Settings settingsC("it {\n"
		"\tstill works\n"
		"}\n");
	CPPUNIT_ASSERT_EQUAL(B_OK, settingsC.ToMessage(kTemplateB, message));
	CPPUNIT_ASSERT_EQUAL(1, message.CountNames(B_ANY_TYPE));
	CPPUNIT_ASSERT_EQUAL(B_OK, message.FindMessage("it", &subMessage));
	CPPUNIT_ASSERT_EQUAL(BString("works"),
		BString(subMessage.GetString("still", "-")));
	CPPUNIT_ASSERT_EQUAL(1, subMessage.CountNames(B_ANY_TYPE));
}


/*static*/ void
DriverSettingsMessageAdapterTest::AddTests(BTestSuite& parent)
{
	CppUnit::TestSuite& suite = *new CppUnit::TestSuite(
		"DriverSettingsMessageAdapterTest");

	suite.addTest(new CppUnit::TestCaller<DriverSettingsMessageAdapterTest>(
		"DriverSettingsMessageAdapterTest::TestPrimitivesToMessage",
		&DriverSettingsMessageAdapterTest::TestPrimitivesToMessage));
	suite.addTest(new CppUnit::TestCaller<DriverSettingsMessageAdapterTest>(
		"DriverSettingsMessageAdapterTest::TestMessage",
		&DriverSettingsMessageAdapterTest::TestMessage));
	suite.addTest(new CppUnit::TestCaller<DriverSettingsMessageAdapterTest>(
		"DriverSettingsMessageAdapterTest::TestParent",
		&DriverSettingsMessageAdapterTest::TestParent));
	suite.addTest(new CppUnit::TestCaller<DriverSettingsMessageAdapterTest>(
		"DriverSettingsMessageAdapterTest::TestConverter",
		&DriverSettingsMessageAdapterTest::TestConverter));
	suite.addTest(new CppUnit::TestCaller<DriverSettingsMessageAdapterTest>(
		"DriverSettingsMessageAdapterTest::TestWildcard",
		&DriverSettingsMessageAdapterTest::TestWildcard));

	parent.addTest("DriverSettingsMessageAdapterTest", &suite);
}