2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 * @file Base64_test.cpp
18 * @author Grzegorz Rynkowski (g.rynkowski@samsung.com)
19 * @brief This file contains tests for Base64
22 #include <Commons/Base64.h>
23 #include <Commons/Exception.h>
24 #include <dpl/log/secure_log.h>
25 #include <dpl/test/test_runner.h>
31 #include <type_traits>
33 using namespace WrtDeviceApis::Commons;
37 TextPair(std::string&& decoded_, std::string&& encoded_)
39 std::swap(decoded_, decoded);
40 std::swap(encoded_, encoded);
42 std::string decoded, encoded;
44 static const std::vector<TextPair>& examples()
46 static std::vector<TextPair> vec = {
48 "Man is distinguished, not only by his reason, but by this sing"
49 "ular passion from other animals, which is a lust of the mind, "
50 "that by a perseverance of delight in the continued and indefat"
51 "igable generation of knowledge, exceeds the short vehemence of"
52 " any carnal pleasure.",
53 "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIG"
54 "J1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxz"
55 "LCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZX"
56 "ZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRlZmF0"
57 "aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZSBzaG"
58 "9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4="),
59 TextPair("f", "Zg=="),
60 TextPair("fo" , "Zm8="),
61 TextPair("foo" , "Zm9v"),
62 TextPair("foob" , "Zm9vYg=="),
63 TextPair("fooba" , "Zm9vYmE=")
70 std::unique_ptr<T[]> convertStringToPtr(const std::string& str)
72 static_assert(std::is_same<unsigned char, T>::value
73 || std::is_same<char, T>::value,
74 "std::string is able convert into char[] or unsigned char[]");
75 std::unique_ptr<T[]> textCopy(new T[str.length() + 1]);
76 std::memcpy(textCopy.get(), str.c_str(), str.length() + 1);
77 return std::move(textCopy);
80 #define CheckEncodeMsg(original_, encoded_, msg) { \
81 std::string original(original_), encoded(encoded_); \
82 std::string methodResult = Base64::encode( \
83 convertStringToPtr<unsigned char>(original).get(), \
85 if (!(methodResult == encoded)) { \
86 _D("Encoded text = \"%s\"", encoded.c_str()); \
87 _D("Base64::encode() = \"%s\"", methodResult.c_str()); \
88 RUNNER_ASSERT(false); \
91 #define CheckEncode(original, encoded) CheckEncodeMsg(original, encoded, "")
93 #define CheckDecodeMsg(encoded_, decoded_, msg) { \
94 std::string encoded(encoded_), decoded(decoded_); \
95 std::string methodResult = Base64::decode(encoded); \
96 if (!(methodResult == decoded)) { \
97 _D("Decoded text = \"%s\"", decoded.c_str()); \
98 _D("Base64::decode() = \"%s\"", methodResult.c_str()); \
99 RUNNER_ASSERT(methodResult == decoded); \
102 #define CheckDecode(original, decoded) CheckDecodeMsg(original, decoded, "")
104 const std::set<char> base64chars = {
105 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
106 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
107 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
108 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
109 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
111 } // unnamed namespace
114 RUNNER_TEST_GROUP_INIT(Base64)
117 Name: base64_test_encode
118 Description: Tests encoding of examples
119 Expected: Base64::encode should encode examples correctly.
121 RUNNER_TEST(base64_test_encode)
123 for (auto& i : TextPair::examples())
124 CheckEncode(i.decoded, i.encoded);
128 Name: base64_test_encode_empty
129 Description: Tests encoding of empty string
130 Expected: Base64::encode should return empty string too
132 RUNNER_TEST(base64_test_encode_empty)
134 CheckEncodeMsg("", "", "Encoded of empty string should be empty too.");
138 Name: base64_test_decode
139 Description: Tests decoding of examples
140 Expected: Base64::encode should decode examples correctly.
142 RUNNER_TEST(base64_test_decode)
144 for (auto& i : TextPair::examples())
145 CheckDecode(i.encoded, i.decoded);
149 Name: base64_test_decode_empty
150 Description: Tests decoding of empty string
151 Expected: Base64::decode should return empty string too
153 RUNNER_TEST(base64_test_decode_empty)
155 CheckDecodeMsg("", "", "Decoded of empty string should be empty too.");
159 Name: base64_test_decode_only_pads
160 Description: Tests decoding of string with only pads
161 Expected: Base64::decode should return empty string
163 RUNNER_TEST(base64_test_decode_only_pads)
165 CheckDecodeMsg("====", "",
166 "Decoded string with only pads should produce empty string");
170 Name: base64_test_decode_invalid_length
171 Description: Tests decoding of string with invalid length
172 Expected: Base64::decode should throw exception
174 RUNNER_TEST(base64_test_decode_invalid_length)
176 for (auto& example : TextPair::examples()) {
177 for (int i = 1; i <= 3; ++i) {
178 std::string encodedWithInvalideLength =
179 example.encoded.substr(0, example.encoded.size() - i);
181 Base64::decode(encodedWithInvalideLength);
182 RUNNER_ASSERT_MSG(false,
183 "For invalid length method should throw exception.");
184 } Catch (InvalidArgumentException) {
185 // Test pass - nothing to do
186 } Catch (DPL::Exception) {
187 RUNNER_ASSERT_MSG(false, "Unknown exception.");
194 Name: base64_test_decode_invalid_valid_char
195 Description: Tests decoding of string with all ASCII characters
196 Expected: Base64::decode should throw exception for characters that aren't
197 in alphabet of Base64.
199 RUNNER_TEST(base64_test_decode_invalid_valid_char)
201 std::random_device rd;
202 std::mt19937 gen(rd());
204 for (const TextPair& ex : TextPair::examples())
206 for (char character = 1; character != 0; ++character)
211 std::string encodedWithNewChar(
212 [&]()->std::string // return string with invalide character
214 std::size_t lastPosition = ex.encoded.find('=');
215 lastPosition = (std::string::npos == lastPosition)
216 ? ex.encoded.length()-1 : lastPosition - 1;
217 std::uniform_int_distribution<> dis(0, lastPosition);
219 int randomPosition = dis(gen);
220 std::unique_ptr<char[]> tmp =
221 convertStringToPtr<char>(ex.encoded);
222 tmp.get()[randomPosition] = character;
223 return std::string(tmp.get());
226 bool found = (base64chars.find(character) != base64chars.end());
228 Base64::decode(encodedWithNewChar);
230 _D("Before = \"%s\"", ex.encoded.c_str());
231 _D("After = \"%s\"", encodedWithNewChar.c_str());
233 RUNNER_ASSERT_MSG(found, "For invalid character("
234 << static_cast<int>(character) << "|'" << character
235 << "') method should throw exception.");
236 } Catch (InvalidArgumentException) {
238 _D("Before = \"%s\"", ex.encoded.c_str());
239 _D("After = \"%s\"", encodedWithNewChar.c_str());
241 RUNNER_ASSERT_MSG(!found, "For valid character("
242 << static_cast<int>(character) << "|'" << character
243 << "') the exception shouldn't be threw.");
244 } Catch (DPL::Exception) {
245 RUNNER_ASSERT_MSG(false, "Unknown exception.");