summaryrefslogtreecommitdiffstats
path: root/bindings/c/Test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'bindings/c/Test.cpp')
-rw-r--r--bindings/c/Test.cpp414
1 files changed, 414 insertions, 0 deletions
diff --git a/bindings/c/Test.cpp b/bindings/c/Test.cpp
new file mode 100644
index 0000000..c450e60
--- /dev/null
+++ b/bindings/c/Test.cpp
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2015, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "ParameterFramework.h"
+
+#define CATCH_CONFIG_MAIN // This tells Catch to provide a main()
+#include <catch.hpp>
+
+#include <string>
+#include <memory>
+#include <vector>
+
+#include <cstring>
+#include <cerrno>
+#include <climits>
+extern "C"
+{
+#include <unistd.h>
+}
+
+struct Test
+{
+ /** @return true if str is empty. */
+ bool empty(const char *str)
+ {
+ REQUIRE(str != NULL);
+ return *str == '\0';
+ }
+
+ void REQUIRE_FAILURE(bool success)
+ {
+ THEN("It should be an error") {
+ INFO("Previous pfw log: \n" + logLines);
+ CAPTURE(pfwGetLastError(pfw));
+ CHECK(not success);
+ CHECK(not empty(pfwGetLastError(pfw)));
+ }
+ }
+
+ void REQUIRE_SUCCESS(bool success)
+ {
+ THEN("It should be a success") {
+ INFO("Previous pfw log: \n" + logLines);
+ CAPTURE(pfwGetLastError(pfw));
+ CHECK(success);
+ CHECK(empty(pfwGetLastError(pfw)));
+ }
+ }
+
+ /** Class to create a temporary file */
+ class TmpFile
+ {
+ public:
+ TmpFile(const std::string &content) {
+ char tmpName[] = "./tmpPfwUnitTestXXXXXX";
+ mFd = mkstemp(tmpName);
+ CAPTURE(errno);
+ REQUIRE(mFd != -1);
+ mPath = tmpName;
+ write(mFd, content.c_str(), content.length());
+ }
+ ~TmpFile() {
+ CHECK(close(mFd) != -1);
+ unlink(mPath.c_str());
+ }
+ operator const char *() const { return mPath.c_str(); }
+ const std::string &path() const { return mPath; }
+ private:
+ std::string mPath;
+ int mFd;
+ };
+
+ /** Log in logLines. */
+ static void logCb(void *voidLogLines, PfwLogLevel level, const char *logLine)
+ {
+ std::string &logLines = *reinterpret_cast<std::string *>(voidLogLines);
+ switch(level) {
+ case pfwLogWarning:
+ logLines += "Warning: ";
+ break;
+ case pfwLogInfo:
+ logLines += "Info: ";
+ }
+ logLines += logLine;
+ logLines += '\n';
+ }
+
+ /** Log buffer, will only be display in case of failure */
+ std::string logLines;
+
+ /** Pfw handler used in the tests. */
+ PfwHandler *pfw;
+
+};
+
+TEST_CASE_METHOD(Test, "Parameter-framework c api use") {
+ // Create criteria
+ const char *letterList[] = {"a", "b", "c", NULL};
+ const char *numberList[] = {"1", "2", "3", NULL};
+ const PfwCriterion criteria[] = {
+ {"inclusiveCrit", true, letterList},
+ {"exclusiveCrit", false, numberList},
+ };
+ size_t criterionNb = sizeof(criteria)/sizeof(criteria[0]);
+ PfwLogger logger = {&logLines, logCb};
+
+ // Create valid pfw config file
+ const char *intParameterPath = "/test/system/integer";
+ const char *stringParameterPath = "/test/system/string";
+ TmpFile system("<?xml version='1.0' encoding='UTF-8'?>\
+ <Subsystem Name='system' Type='Virtual' Endianness='Little'>\
+ <ComponentLibrary/>\
+ <InstanceDefinition>\
+ <IntegerParameter Name='integer' Size='32' Signed='true' Max='100'/>\
+ <StringParameter Name='string' MaxLength='9'/>\
+ </InstanceDefinition>\
+ </Subsystem>");
+ TmpFile libraries("<?xml version='1.0' encoding='UTF-8'?>\
+ <SystemClass Name='test'>\
+ <SubsystemInclude Path='" + system.path() + "'/>\
+ </SystemClass>");
+ TmpFile config("<?xml version='1.0' encoding='UTF-8'?>\
+ <ParameterFrameworkConfiguration\
+ SystemClassName='test' TuningAllowed='false'>\
+ <SubsystemPlugins/>\
+ <StructureDescriptionFileLocation Path='" + libraries.path() + "'/>\
+ </ParameterFrameworkConfiguration>");
+
+ GIVEN("A created parameter framework") {
+ pfw = pfwCreate();
+ REQUIRE(pfw != NULL);
+
+ THEN("Error message should be empty") {
+ CHECK(empty(pfwGetLastError(pfw)));
+ }
+
+ WHEN("The pfw is started without an handler") {
+ CHECK(not pfwStart(NULL, config, criteria, criterionNb, &logger));
+ }
+ WHEN("The pfw is started without a config path") {
+ REQUIRE_FAILURE(pfwStart(pfw, NULL, criteria, criterionNb, &logger));
+ }
+ WHEN("The pfw is started without an existent file") {
+ REQUIRE_FAILURE(pfwStart(pfw, "/doNotExist", criteria, criterionNb, &logger));
+ }
+
+ WHEN("The pfw is started without a criteria list") {
+ REQUIRE_FAILURE(pfwStart(pfw, config, NULL, criterionNb, &logger));
+ }
+ WHEN("The pfw is started with duplicated criterion value") {
+ const PfwCriterion duplicatedCriteria[] = {
+ {"duplicated name", true, letterList},
+ {"duplicated name", false, numberList},
+ };
+ REQUIRE_FAILURE(pfwStart(pfw, config, duplicatedCriteria, 2, &logger));
+ }
+ WHEN("The pfw is started with duplicated criterion value state") {
+ const char * values[] = {"a", "a", NULL};
+ const PfwCriterion duplicatedCriteria[] = {{"name", true, values}};
+
+ WHEN("Using test logger") {
+ REQUIRE_FAILURE(pfwStart(pfw, config, duplicatedCriteria, 1, &logger));
+ }
+ WHEN("Using default logger") {
+ // Test coverage of default logger warning
+ REQUIRE_FAILURE(pfwStart(pfw, config, duplicatedCriteria, 1, NULL));
+ }
+ }
+ WHEN("The pfw is started with NULL name criterion") {
+ const PfwCriterion duplicatedCriteria[] = {{NULL, true, letterList}};
+ REQUIRE_FAILURE(pfwStart(pfw, config, duplicatedCriteria, 1, &logger));
+ }
+ WHEN("The pfw is started with NULL criterion state list") {
+ const PfwCriterion duplicatedCriteria[] = {{"name", true, NULL}};
+ REQUIRE_FAILURE(pfwStart(pfw, config, duplicatedCriteria, 1, &logger));
+ }
+ GIVEN("A criteria with lots of values")
+ {
+ // Build a criterion with as many value as there is bits in int.
+ std::vector<char> names(sizeof(int) * CHAR_BIT + 1, 'a');
+ names.back() = '\0';
+ std::vector<const char *> values(names.size());
+ for(size_t i = 0; i < values.size(); ++i) {
+ values[i] = &names[i];
+ }
+ values.back() = NULL;
+ /* The pfw c api requires criterion values to be a NULL terminated
+ * array of string. Each string is a pointer to a NULL terminated
+ * array of char. The pfw requires each string to be different
+ * from all others, ie strcmp(values[i], values[j]) != 0 for any
+ * i j.
+ *
+ * In order to generate easily an array of different strings,
+ * instantiate one string (names) big enough
+ * (@see PfwCriterion::values).
+ * Then instantiate an array of pointer (values),
+ * each pointing to a different position in the previously
+ * created string.
+ *
+ * Representation of the names and values vectors.
+ *
+ * n = number of bit in an int
+ * <--- n+1 elements --->
+ * names = |a|a|a|a|...|a|a|a|\0|
+ * ^ ^ ^
+ * values[0] = ´ | |
+ * values[1] = --´ |
+ * ... |
+ * values[n - 1] = -----------´
+ * values[n] = NULL
+ *
+ */
+ const PfwCriterion duplicatedCriteria[] = {{"name", true, &values[0]}};
+
+ WHEN("The pfw is started with a too long criterion state list") {
+ REQUIRE_FAILURE(pfwStart(pfw, config, duplicatedCriteria, 1, &logger));
+ }
+ WHEN("The pfw is started with max length criterion state list") {
+ values[values.size() - 2] = NULL; // Hide last value
+ REQUIRE_SUCCESS(pfwStart(pfw, config, duplicatedCriteria, 1, &logger));
+ }
+ }
+
+ WHEN("The pfw is started with zero criteria") {
+ REQUIRE_SUCCESS(pfwStart(pfw, config, criteria, 0, &logger));
+ }
+
+ WHEN("The pfw is started twice a pfw") {
+ REQUIRE_SUCCESS(pfwStart(pfw, config, criteria, criterionNb, &logger));
+ REQUIRE_FAILURE(pfwStart(pfw, config, criteria, criterionNb, &logger));
+ }
+
+ WHEN("The pfw is started without a logger callback") {
+ PfwLogger noLog = { NULL, NULL };
+ REQUIRE_SUCCESS(pfwStart(pfw, config, criteria, criterionNb, &noLog));
+ }
+ WHEN("The pfw is started with default logger") {
+ REQUIRE_SUCCESS(pfwStart(pfw, config, criteria, criterionNb, NULL));
+ }
+
+ WHEN("Get criterion of a stopped pfw") {
+ int value;
+ REQUIRE_FAILURE(pfwGetCriterion(pfw, criteria[0].name, &value));
+ }
+ WHEN("Set criterion of a stopped pfw") {
+ REQUIRE_FAILURE(pfwSetCriterion(pfw, criteria[0].name, 1));
+ }
+ WHEN("Commit criteria of a stopped pfw") {
+ REQUIRE_FAILURE(pfwApplyConfigurations(pfw));
+ }
+
+ WHEN("Bind parameter with a stopped pfw") {
+ REQUIRE(pfwBindParameter(pfw, intParameterPath) == NULL);
+ }
+
+ WHEN("The pfw is started correctly")
+ {
+ REQUIRE_SUCCESS(pfwStart(pfw, config, criteria, criterionNb, &logger));
+ int value;
+
+ WHEN("Get criterion without an handle") {
+ REQUIRE(not pfwGetCriterion(NULL, criteria[0].name, &value));
+ }
+ WHEN("Get criterion without a name") {
+ REQUIRE_FAILURE(pfwGetCriterion(pfw, NULL, &value));
+ }
+ WHEN("Get criterion without an output value") {
+ REQUIRE_FAILURE(pfwGetCriterion(pfw, criteria[0].name, NULL));
+ }
+ WHEN("Get not existing criterion") {
+ REQUIRE_FAILURE(pfwGetCriterion(pfw, "Do not exist", &value));
+ }
+ THEN("All criterion should value 0") {
+ for(size_t i = 0; i < criterionNb; ++i) {
+ const char *criterionName = criteria[i].name;
+ CAPTURE(criterionName);
+ REQUIRE_SUCCESS(pfwGetCriterion(pfw, criterionName, &value));
+ REQUIRE(value == 0);
+ }
+ }
+
+ WHEN("Set criterion without an handle") {
+ REQUIRE(not pfwSetCriterion(NULL, criteria[0].name, 1));
+ }
+ WHEN("Set criterion without a name") {
+ REQUIRE_FAILURE(pfwSetCriterion(pfw, NULL, 2));
+ }
+ WHEN("Set not existing criterion") {
+ REQUIRE_FAILURE(pfwSetCriterion(pfw, "Do not exist", 3));
+ }
+ WHEN("Set criterion value") {
+ for(size_t i = 0; i < criterionNb; ++i) {
+ const char *criterionName = criteria[i].name;
+ CAPTURE(criterionName);
+ REQUIRE_SUCCESS(pfwSetCriterion(pfw, criterionName, 3));
+ }
+ THEN("Get criterion value should return what was set") {
+ for(size_t i = 0; i < criterionNb; ++i) {
+ const char *criterionName = criteria[i].name;
+ CAPTURE(criterionName);
+ REQUIRE_SUCCESS(pfwGetCriterion(pfw, criterionName, &value));
+ REQUIRE(value == 3);
+ }
+ }
+ }
+ WHEN("Commit criteria without a pfw") {
+ REQUIRE(not pfwApplyConfigurations(NULL));
+ }
+ WHEN("Commit criteria of a started pfw") {
+ REQUIRE_SUCCESS(pfwApplyConfigurations(pfw));
+ }
+
+ WHEN("Bind parameter without a pfw") {
+ REQUIRE(pfwBindParameter(NULL, intParameterPath) == NULL);
+ }
+ WHEN("Bind parameter without a path") {
+ REQUIRE_FAILURE(pfwBindParameter(pfw, NULL) != NULL);
+ }
+ WHEN("Bind a non existing parameter") {
+ REQUIRE_FAILURE(pfwBindParameter(pfw, "do/not/exist") != NULL);
+ }
+
+ WHEN("Set an int parameter without a parameter handle") {
+ REQUIRE(not pfwSetIntParameter(NULL, value));
+ }
+ WHEN("Get an int parameter without a parameter handle") {
+ REQUIRE(not pfwGetIntParameter(NULL, &value));
+ }
+
+ GIVEN("An integer parameter handle") {
+ PfwParameterHandler *param = pfwBindParameter(pfw, intParameterPath);
+ REQUIRE_SUCCESS(param != NULL);
+
+ WHEN("Get an int parameter without an output value") {
+ REQUIRE_FAILURE(pfwGetIntParameter(param, NULL));
+ }
+
+ WHEN("Set parameter out of range") {
+ REQUIRE_FAILURE(pfwSetIntParameter(param, 101));
+ }
+
+ WHEN("Set parameter") {
+ REQUIRE_SUCCESS(pfwSetIntParameter(param, 11));
+ THEN("Get parameter should return what was set") {
+ REQUIRE_SUCCESS(pfwGetIntParameter(param, &value));
+ REQUIRE(value == 11);
+ }
+ }
+
+ pfwUnbindParameter(param);
+ }
+
+ GIVEN("An string parameter handle") {
+ PfwParameterHandler *param = pfwBindParameter(pfw, stringParameterPath);
+ REQUIRE_SUCCESS(param != NULL);
+
+ WHEN("Get an int parameter without an output value") {
+ REQUIRE_FAILURE(pfwGetStringParameter(param, NULL));
+ }
+
+ WHEN("Set parameter out of range") {
+ REQUIRE_FAILURE(pfwSetStringParameter(param, "ko_1234567"));
+ }
+
+ WHEN("Set parameter") {
+ const char *value;
+ REQUIRE_SUCCESS(pfwSetStringParameter(param, "ok"));
+ THEN("Get parameter should return what was set") {
+ REQUIRE_SUCCESS(pfwGetStringParameter(param, &value));
+ REQUIRE(value == std::string("ok"));
+ pfwFree((void *)value);
+ }
+ }
+
+ pfwUnbindParameter(param);
+ }
+ }
+
+ pfwDestroy(pfw);
+ }
+}
+
+SCENARIO("Get last error without a pfw") {
+ THEN("Should return NULL") {
+ CHECK(pfwGetLastError(NULL) == NULL);
+ }
+}