summaryrefslogtreecommitdiff
path: root/src/components/smart_objects/test/SmartObjectStress_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/smart_objects/test/SmartObjectStress_test.cc')
-rw-r--r--src/components/smart_objects/test/SmartObjectStress_test.cc336
1 files changed, 336 insertions, 0 deletions
diff --git a/src/components/smart_objects/test/SmartObjectStress_test.cc b/src/components/smart_objects/test/SmartObjectStress_test.cc
new file mode 100644
index 000000000..4fb7b2efc
--- /dev/null
+++ b/src/components/smart_objects/test/SmartObjectStress_test.cc
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2014, Ford Motor Company
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 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.
+ *
+ * Neither the name of the Ford Motor Company 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 <sstream>
+#include "gmock/gmock.h"
+#include "smart_objects/smart_object.h"
+
+//#define NO_INCLUSIVE_MAPS
+//#define COPY_SUB_OBJECTS_WORKAROUND
+
+namespace test {
+namespace components {
+namespace SmartObjects {
+namespace SmartObjectStressTest {
+
+using namespace NsSmartDeviceLink::NsSmartObjects;
+
+class StressTestHelper : public ::testing::Test {
+ private:
+ char get_random_char() const {
+ return static_cast<char>('A' + (rand() % 52));
+ }
+
+ std::string to_string(const int value) const {
+ std::ostringstream oss;
+ oss << value;
+ return oss.str();
+ }
+
+ std::string to_string(const double value) const {
+ // Content is the same as in SmartObject::convert_double_to_string
+ std::stringstream ss;
+ ss << std::fixed << std::setprecision(10) << value; //convert double to string w fixed notation, hi precision
+ std::string s = ss.str(); //output to std::string
+ s.erase(s.find_last_not_of('0') + 1, std::string::npos); //remove trailing 000s (123.1200 => 123.12, 123.000 => 123.)
+ if (s[s.size() - 1] == '.') {
+ s.erase(s.end() - 1); //remove dangling decimal (123. => 123)
+ }
+ return s;
+ }
+
+ std::string to_string(const char ch) const {
+ char buff[2];
+ sprintf(buff, "%c", ch);
+ return std::string(buff);
+ }
+
+ std::string to_string(const bool b) const {
+ return std::string((b) ? "true" : "false");
+ }
+
+ protected:
+ typedef std::map<std::string, std::string> VerificationMap;
+ VerificationMap mVerifyMap;
+
+ std::vector<std::string> split(const std::string &s, char delim) const {
+ std::vector < std::string > elems;
+
+ std::stringstream ss(s);
+ std::string item;
+ while (std::getline(ss, item, delim)) {
+ elems.push_back(item);
+ }
+
+ return elems;
+ }
+
+ std::string generate_key(const char *pPrefix, const int index) const {
+ char buff[32];
+ sprintf(buff, "%s%d", pPrefix, index);
+ return std::string(buff);
+ }
+
+ void makeRandomObject(SmartObject &obj, const int size,
+ std::string key_path) {
+ int type_id = rand() % 8;
+
+ switch (type_id) {
+ case 0: // int
+ {
+ int iVal = rand();
+ obj = iVal;
+ mVerifyMap[key_path] = to_string(iVal);
+ //std::cout << "Created int, value: " << iVal << std::endl;
+ break;
+ }
+ case 1: // bool
+ {
+ bool bVal = static_cast<bool>(rand() % 2);
+ obj = bVal;
+ mVerifyMap[key_path] = to_string(bVal);
+ //std::cout << "Created bool, value: " << to_string(bVal) << std::endl;
+ break;
+ }
+ case 2: // double
+ {
+ double dVal = 100.0 / (rand() % 200);
+ obj = dVal;
+ mVerifyMap[key_path] = to_string(dVal);
+ //std::cout << "Created double, value: " << dVal << std::endl;
+ break;
+ }
+ case 3: // char
+ {
+ char cVal = get_random_char();
+ obj = cVal;
+ mVerifyMap[key_path] = to_string(cVal);
+ //std::cout << "Created char, value: " << cVal << std::endl;
+ break;
+ }
+ case 4: // string
+ {
+ std::string strVal(rand() % 200, get_random_char());
+ obj = strVal; // string with random char filled random size
+ mVerifyMap[key_path] = strVal;
+ //std::cout << "Created string, value: " << strVal << std::endl;
+ break;
+ }
+ case 5: // map
+ if (size <= 0)
+ break;
+
+ //std::cout << "Creating a map with size: " << size << std::endl;
+ mVerifyMap[key_path] = "map";
+ for (int i = 0; i < size; i++) {
+ std::string key = generate_key("M", i);
+#ifdef NO_INCLUSIVE_MAPS
+ obj[key] = key;
+#else
+ obj[key] = SmartObject();
+ makeRandomObject(obj[key], size - 1, key_path + key + ' '); // recursion
+#endif // MAP_WORKAROUND
+ }
+ break;
+ case 6: // array
+ if (size <= 0)
+ break;
+
+ //std::cout << "Creating an array with size: " << size << std::endl;
+ mVerifyMap[key_path] = "array";
+ for (int i = 0; i < size; i++) {
+ obj[i] = SmartObject(); // just init it as an array
+ makeRandomObject(obj[i], size - 1,
+ key_path + generate_key("A", i) + ' '); // recursion
+ }
+ break;
+ case 7: // binary
+ int dataSize = rand() % 200;
+ char randomChar = get_random_char();
+ std::string strDataVal(dataSize, randomChar);
+ std::string strVal("c:");
+ strVal += strDataVal;
+
+ NsSmartDeviceLink::NsSmartObjects::SmartBinary binaryVal(dataSize,
+ randomChar);
+
+ obj = binaryVal; // string with binary data filled with random chars
+ mVerifyMap[key_path] = strVal;
+ //std::cout << "Created string, value: " << strVal << std::endl;
+ break;
+ }
+ }
+
+ SmartObject get_object(SmartObject &rootObj, const std::string &path) const {
+ std::vector < std::string > obj_tokens;
+ SmartObject lastObj = rootObj;
+
+ obj_tokens = split(path, ' ');
+
+ for (size_t i = 0; i < obj_tokens.size(); i++) {
+ if (obj_tokens[i][0] == 'A') // array
+ {
+ int index = atoi(&(obj_tokens[i].c_str()[1])); // get integer skipping first char
+#ifdef COPY_SUB_OBJECTS_WORKAROUND
+ lastObj = SmartObject(lastObj[index]);
+#else
+ lastObj = lastObj[index]; // go to the child object
+#endif
+ } else if (obj_tokens[i][0] == 'M') // map
+ {
+#ifdef COPY_SUB_OBJECTS_WORKAROUND
+ lastObj = SmartObject(lastObj[obj_tokens[i]]);
+#else
+ lastObj = lastObj[obj_tokens[i]]; // go to the child object
+#endif
+ } else {
+ //FAIL();
+ EXPECT_TRUE(false);
+ }
+ }
+ return lastObj;
+ }
+};
+
+/*
+ * The test creates the initial SmartObject and use it as an array for the next SmartObjects.
+ * Each next SmartObject is randomly assigned to some type.
+ * If one of the object happens to be a container it fills it with SmartObject of random type. The amount of these
+ * objects is the size of the parent container -1.
+ * The iteration continues until all nodes are simple SmartObjects (not arrays or maps)
+ */
+TEST_F(StressTestHelper, StressTest) {
+ SmartObject objects;
+
+ const int size = 11;
+
+ for (int i = 0; i < size; i++) {
+ SmartObject obj;
+
+ makeRandomObject(obj, size - 1, generate_key("A", i) + ' ');
+
+ objects[i] = obj;
+ }
+
+ for (VerificationMap::const_iterator it = mVerifyMap.begin();
+ it != mVerifyMap.end(); it++) {
+ std::string value(it->second);
+ SmartObject obj = get_object(objects, it->first);
+
+ // Binary data check
+ if (!value.compare(0, 2, "c:")) {
+ std::string etalonData = value.substr(2);
+
+ ASSERT_EQ(NsSmartDeviceLink::NsSmartObjects::SmartType_Binary,
+ obj.getType());
+
+ NsSmartDeviceLink::NsSmartObjects::SmartBinary binaryData =
+ obj.asBinary();
+ ASSERT_EQ(etalonData.size(), binaryData.size());
+
+ for (size_t i = 0; i < etalonData.size(); ++i) {
+ {
+ std::string etalonData = value.substr(2);
+
+ ASSERT_EQ(NsSmartDeviceLink::NsSmartObjects::SmartType_Binary,
+ obj.getType());
+
+ NsSmartDeviceLink::NsSmartObjects::SmartBinary binaryData = obj
+ .asBinary();
+ ASSERT_EQ(etalonData.size(), binaryData.size());
+
+ for (size_t i = 0; i < etalonData.size(); ++i) {
+ ASSERT_EQ(etalonData.at(i), binaryData.at(i));
+ }
+ continue;
+ }
+
+ ASSERT_EQ(etalonData.at(i), binaryData.at(i));
+ }
+ continue;
+ }
+
+#ifdef NO_INCLUSIVE_MAPS
+ if (!value.compare("map"))
+ {
+ std::vector<std::string> path = split(it->first, ' ');
+
+ std::string map_value = path[path.size()-1];
+ ASSERT_EQ(map_value, static_cast<std::string>(obj));
+ continue;
+ }
+#endif
+ if (value.compare("map") && value.compare("array")) {
+ //std::cout << "Verification key: " << it->first << " Value: " << value << std::endl;
+ //std::cout << "Object Value: " << static_cast<std::string>(obj) << std::endl;
+
+ if (!value.compare("true")) {
+ ASSERT_TRUE(obj.asBool());
+ } else if (!value.compare("false")) {
+ ASSERT_FALSE(obj.asBool());
+ } else {
+ ASSERT_EQ(value, obj.asString())<< "Object value is not correct. Object path: " << it->first;
+ }
+ }
+ }
+}
+
+TEST_F(StressTestHelper, ExtraManualDebugTest) {
+ SmartObject obj;
+
+ obj[0] = false;
+ obj[1] = 0.869495;
+ obj[2] = true;
+ obj[3] = 'Q';
+ obj[4] = true;
+ obj[5] = 3.704;
+ obj[6] = SmartObject();
+ obj[6][0] =
+ std::string(
+ "ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt");
+ obj[6][1] = 'K';
+ obj[6][2] = 0.735294;
+ obj[6][3] = 'I';
+ obj[6][4] = SmartObject();
+ obj[6][4]["M0"] = 0.59432;
+ SmartObject & refObj = obj[6][4];
+ refObj["M1"]["M0"]["M0"][0] = true;
+
+ // FIXME: Figure out why there's a trailing zero while converting from double to string
+ ASSERT_EQ("0.59432", get_object(obj, "A6 A4 M0").asString());
+ ASSERT_TRUE(get_object(obj, "A6 A4 M1 M0 M0 A0").asBool());
+}
+
+}
+}
+}
+}