summaryrefslogtreecommitdiff
path: root/tests/Commons/Base64_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/Commons/Base64_test.cpp')
-rw-r--r--tests/Commons/Base64_test.cpp249
1 files changed, 249 insertions, 0 deletions
diff --git a/tests/Commons/Base64_test.cpp b/tests/Commons/Base64_test.cpp
new file mode 100644
index 0000000..afa1a1c
--- /dev/null
+++ b/tests/Commons/Base64_test.cpp
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @file Base64_test.cpp
+ * @author Grzegorz Rynkowski (g.rynkowski@samsung.com)
+ * @brief This file contains tests for Base64
+ */
+
+#include <Commons/Base64.h>
+#include <Commons/Exception.h>
+#include <dpl/log/secure_log.h>
+#include <dpl/test/test_runner.h>
+#include <cstring>
+#include <memory>
+#include <random>
+#include <set>
+#include <string>
+#include <type_traits>
+
+using namespace WrtDeviceApis::Commons;
+
+namespace {
+struct TextPair {
+ TextPair(std::string&& decoded_, std::string&& encoded_)
+ {
+ std::swap(decoded_, decoded);
+ std::swap(encoded_, encoded);
+ }
+ std::string decoded, encoded;
+
+ static const std::vector<TextPair>& examples()
+ {
+ static std::vector<TextPair> vec = {
+ TextPair(
+ "Man is distinguished, not only by his reason, but by this sing"
+ "ular passion from other animals, which is a lust of the mind, "
+ "that by a perseverance of delight in the continued and indefat"
+ "igable generation of knowledge, exceeds the short vehemence of"
+ " any carnal pleasure.",
+ "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIG"
+ "J1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxz"
+ "LCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZX"
+ "ZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0"
+ "aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG"
+ "9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4="),
+ TextPair("f", "Zg=="),
+ TextPair("fo" , "Zm8="),
+ TextPair("foo" , "Zm9v"),
+ TextPair("foob" , "Zm9vYg=="),
+ TextPair("fooba" , "Zm9vYmE=")
+ };
+ return vec;
+ }
+};
+
+template<typename T>
+std::unique_ptr<T[]> convertStringToPtr(const std::string& str)
+{
+ static_assert(std::is_same<unsigned char, T>::value
+ || std::is_same<char, T>::value,
+ "std::string is able convert into char[] or unsigned char[]");
+ std::unique_ptr<T[]> textCopy(new T[str.length() + 1]);
+ std::memcpy(textCopy.get(), str.c_str(), str.length() + 1);
+ return std::move(textCopy);
+}
+
+#define CheckEncodeMsg(original_, encoded_, msg) { \
+ std::string original(original_), encoded(encoded_); \
+ std::string methodResult = Base64::encode( \
+ convertStringToPtr<unsigned char>(original).get(), \
+ original.length()); \
+ if (!(methodResult == encoded)) { \
+ WrtLogD("Encoded text = \"%s\"", encoded.c_str()); \
+ WrtLogD("Base64::encode() = \"%s\"", methodResult.c_str()); \
+ RUNNER_ASSERT(false); \
+ } \
+}
+#define CheckEncode(original, encoded) CheckEncodeMsg(original, encoded, "")
+
+#define CheckDecodeMsg(encoded_, decoded_, msg) { \
+ std::string encoded(encoded_), decoded(decoded_); \
+ std::string methodResult = Base64::decode(encoded); \
+ if (!(methodResult == decoded)) { \
+ WrtLogD("Decoded text = \"%s\"", decoded.c_str()); \
+ WrtLogD("Base64::decode() = \"%s\"", methodResult.c_str()); \
+ RUNNER_ASSERT(methodResult == decoded); \
+ } \
+}
+#define CheckDecode(original, decoded) CheckDecodeMsg(original, decoded, "")
+
+const std::set<char> base64chars = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
+ 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
+
+} // unnamed namespace
+
+
+RUNNER_TEST_GROUP_INIT(Base64)
+
+/*
+Name: base64_test_encode
+Description: Tests encoding of examples
+Expected: Base64::encode should encode examples correctly.
+*/
+RUNNER_TEST(base64_test_encode)
+{
+ for (auto& i : TextPair::examples())
+ CheckEncode(i.decoded, i.encoded);
+}
+
+/*
+Name: base64_test_encode_empty
+Description: Tests encoding of empty string
+Expected: Base64::encode should return empty string too
+*/
+RUNNER_TEST(base64_test_encode_empty)
+{
+ CheckEncodeMsg("", "", "Encoded of empty string should be empty too.");
+}
+
+/*
+Name: base64_test_decode
+Description: Tests decoding of examples
+Expected: Base64::encode should decode examples correctly.
+*/
+RUNNER_TEST(base64_test_decode)
+{
+ for (auto& i : TextPair::examples())
+ CheckDecode(i.encoded, i.decoded);
+}
+
+/*
+Name: base64_test_decode_empty
+Description: Tests decoding of empty string
+Expected: Base64::decode should return empty string too
+*/
+RUNNER_TEST(base64_test_decode_empty)
+{
+ CheckDecodeMsg("", "", "Decoded of empty string should be empty too.");
+}
+
+/*
+Name: base64_test_decode_only_pads
+Description: Tests decoding of string with only pads
+Expected: Base64::decode should return empty string
+*/
+RUNNER_TEST(base64_test_decode_only_pads)
+{
+ CheckDecodeMsg("====", "",
+ "Decoded string with only pads should produce empty string");
+}
+
+/*
+Name: base64_test_decode_invalid_length
+Description: Tests decoding of string with invalid length
+Expected: Base64::decode should throw exception
+*/
+RUNNER_TEST(base64_test_decode_invalid_length)
+{
+ for (auto& example : TextPair::examples()) {
+ for (int i = 1; i <= 3; ++i) {
+ std::string encodedWithInvalideLength =
+ example.encoded.substr(0, example.encoded.size() - i);
+ Try {
+ Base64::decode(encodedWithInvalideLength);
+ RUNNER_ASSERT_MSG(false,
+ "For invalid length method should throw exception.");
+ } Catch (InvalidArgumentException) {
+ // Test pass - nothing to do
+ } Catch (DPL::Exception) {
+ RUNNER_ASSERT_MSG(false, "Unknown exception.");
+ }
+ }
+ }
+}
+
+/*
+Name: base64_test_decode_invalid_valid_char
+Description: Tests decoding of string with all ASCII characters
+Expected: Base64::decode should throw exception for characters that aren't
+ in alphabet of Base64.
+*/
+RUNNER_TEST(base64_test_decode_invalid_valid_char)
+{
+ std::random_device rd;
+ std::mt19937 gen(rd());
+
+ for (const TextPair& ex : TextPair::examples())
+ {
+ for (char character = 1; character != 0; ++character)
+ {
+ if('=' == character)
+ continue;
+
+ std::string encodedWithNewChar(
+ [&]()->std::string // return string with invalide character
+ {
+ std::size_t lastPosition = ex.encoded.find('=');
+ lastPosition = (std::string::npos == lastPosition)
+ ? ex.encoded.length()-1 : lastPosition - 1;
+ std::uniform_int_distribution<> dis(0, lastPosition);
+
+ int randomPosition = dis(gen);
+ std::unique_ptr<char[]> tmp =
+ convertStringToPtr<char>(ex.encoded);
+ tmp.get()[randomPosition] = character;
+ return std::string(tmp.get());
+ }());
+
+ bool found = (base64chars.find(character) != base64chars.end());
+ Try {
+ Base64::decode(encodedWithNewChar);
+ if (!found) {
+ WrtLogD("Before = \"%s\"", ex.encoded.c_str());
+ WrtLogD("After = \"%s\"", encodedWithNewChar.c_str());
+ }
+ RUNNER_ASSERT_MSG(found, "For invalid character("
+ << static_cast<int>(character) << "|'" << character
+ << "') method should throw exception.");
+ } Catch (InvalidArgumentException) {
+ if (found) {
+ WrtLogD("Before = \"%s\"", ex.encoded.c_str());
+ WrtLogD("After = \"%s\"", encodedWithNewChar.c_str());
+ }
+ RUNNER_ASSERT_MSG(!found, "For valid character("
+ << static_cast<int>(character) << "|'" << character
+ << "') the exception shouldn't be threw.");
+ } Catch (DPL::Exception) {
+ RUNNER_ASSERT_MSG(false, "Unknown exception.");
+ }
+ }
+ }
+}