1/*
2 Copyright (c) 2016 Contributors as noted in the AUTHORS file
3
4 This file is part of libzmq, the ZeroMQ core engine in C++.
5
6 libzmq is free software; you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License (LGPL) as published
8 by the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 As a special exception, the Contributors give you permission to link
12 this library with independent modules to produce an executable,
13 regardless of the license terms of these independent modules, and to
14 copy and distribute the resulting executable under terms of your choice,
15 provided that you also meet, for each linked independent module, the
16 terms and conditions of the license of that module. An independent
17 module is a module which is not derived from or based on this library.
18 If you modify this library, you must extend this exception to your
19 version of the library.
20
21 libzmq is distributed in the hope that it will be useful, but WITHOUT
22 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24 License for more details.
25
26 You should have received a copy of the GNU Lesser General Public License
27 along with this program. If not, see <http://www.gnu.org/licenses/>.
28*/
29
30#include "testutil.hpp"
31#include "testutil_unity.hpp"
32
33void setUp ()
34{
35}
36
37void tearDown ()
38{
39}
40
41// Test vector: rfc.zeromq.org/spec:32/Z85
42void test__zmq_z85_encode__valid__success ()
43{
44 static const size_t size = 8;
45 static const size_t length = size * 5 / 4;
46 static const uint8_t decoded[size] = {0x86, 0x4F, 0xD2, 0x6F,
47 0xB5, 0x59, 0xF7, 0x5B};
48 static const char expected[length + 1] = "HelloWorld";
49 char out_encoded[length + 1] = {0};
50
51 errno = 0;
52 TEST_ASSERT_NOT_NULL (zmq_z85_encode (out_encoded, decoded, size));
53 TEST_ASSERT_EQUAL_STRING (expected, out_encoded);
54 TEST_ASSERT_EQUAL_INT (0, zmq_errno ());
55}
56
57// Buffer length must be evenly divisible by 4 or must fail with EINVAL.
58void test__zmq_z85_encode__invalid__failure (size_t size_)
59{
60 errno = 0;
61 TEST_ASSERT_NULL (zmq_z85_encode (NULL, NULL, size_));
62 TEST_ASSERT_EQUAL_INT (EINVAL, zmq_errno ());
63}
64
65// Test vector: rfc.zeromq.org/spec:32/Z85
66void test__zmq_z85_decode__valid__success ()
67{
68 static const size_t size = 10 * 4 / 5;
69 static const uint8_t expected[size] = {0x86, 0x4F, 0xD2, 0x6F,
70 0xB5, 0x59, 0xF7, 0x5B};
71 static const char *encoded = "HelloWorld";
72 uint8_t out_decoded[size] = {0};
73
74 errno = 0;
75 TEST_ASSERT_NOT_NULL (zmq_z85_decode (out_decoded, encoded));
76 TEST_ASSERT_EQUAL_INT (0, zmq_errno ());
77 TEST_ASSERT_EQUAL_UINT8_ARRAY (expected, out_decoded, size);
78}
79
80// Invalid input data must fail with EINVAL.
81template <size_t SIZE>
82void test__zmq_z85_decode__invalid__failure (const char (&encoded_)[SIZE])
83{
84 uint8_t decoded[SIZE * 4 / 5 + 1];
85 errno = 0;
86 TEST_ASSERT_NULL (zmq_z85_decode (decoded, encoded_));
87 TEST_ASSERT_EQUAL_INT (EINVAL, zmq_errno ());
88}
89
90
91// call zmq_z85_encode, then zmq_z85_decode, and compare the results with the original
92template <size_t SIZE>
93void test__zmq_z85_encode__zmq_z85_decode__roundtrip (
94 const uint8_t (&test_data_)[SIZE])
95{
96 char test_data_z85[SIZE * 5 / 4 + 1];
97 char *res1 = zmq_z85_encode (test_data_z85, test_data_, SIZE);
98 TEST_ASSERT_NOT_NULL (res1);
99
100 uint8_t test_data_decoded[SIZE];
101 uint8_t *res2 = zmq_z85_decode (test_data_decoded, test_data_z85);
102 TEST_ASSERT_NOT_NULL (res2);
103
104 TEST_ASSERT_EQUAL_UINT8_ARRAY (test_data_, test_data_decoded, SIZE);
105}
106
107// call zmq_z85_encode, then zmq_z85_decode, and compare the results with the original
108template <size_t SIZE>
109void test__zmq_z85_decode__zmq_z85_encode__roundtrip (
110 const char (&test_data_)[SIZE])
111{
112 const size_t decoded_size = (SIZE - 1) * 4 / 5;
113 uint8_t test_data_decoded[decoded_size];
114 uint8_t *res1 = zmq_z85_decode (test_data_decoded, test_data_);
115 TEST_ASSERT_NOT_NULL (res1);
116
117 char test_data_z85[SIZE];
118 char *res2 =
119 zmq_z85_encode (test_data_z85, test_data_decoded, decoded_size);
120 TEST_ASSERT_NOT_NULL (res2);
121
122 TEST_ASSERT_EQUAL_UINT8_ARRAY (test_data_, test_data_z85, SIZE);
123}
124
125#define def_test__zmq_z85_basename(basename, name, param) \
126 void test__zmq_z85_##basename##_##name () \
127 { \
128 test__zmq_z85_##basename (param); \
129 }
130
131#define def_test__zmq_z85_encode__invalid__failure(name, param) \
132 def_test__zmq_z85_basename (encode__invalid__failure, name, param)
133
134def_test__zmq_z85_encode__invalid__failure (1, 1)
135 def_test__zmq_z85_encode__invalid__failure (42, 42)
136
137#define def_test__zmq_z85_decode__invalid__failure(name, param) \
138 def_test__zmq_z85_basename (decode__invalid__failure, name, param)
139
140 // String length must be evenly divisible by 5 or must fail with EINVAL.
141 def_test__zmq_z85_decode__invalid__failure (indivisble_by_5_multiple_chars,
142 "01234567")
143 def_test__zmq_z85_decode__invalid__failure (indivisble_by_5_one_char, "0")
144
145 // decode invalid data with the maximum representable value
146 def_test__zmq_z85_decode__invalid__failure (max, "#####")
147
148 // decode invalid data with the minimum value beyond the limit
149 // "%nSc0" is 0xffffffff
150 def_test__zmq_z85_decode__invalid__failure (above_limit, "%nSc1")
151
152 // decode invalid data with an invalid character in the range of valid
153 // characters
154 def_test__zmq_z85_decode__invalid__failure (char_within, "####\0047")
155
156 // decode invalid data with an invalid character just below the range of valid
157 // characters
158 def_test__zmq_z85_decode__invalid__failure (char_adjacent_below, "####\0200")
159
160 // decode invalid data with an invalid character just above the range of valid
161 // characters
162 def_test__zmq_z85_decode__invalid__failure (char_adjacent_above, "####\0037")
163
164#define def_test__encode__zmq_z85_decode__roundtrip(name, param) \
165 def_test__zmq_z85_basename (encode__zmq_z85_decode__roundtrip, name, param)
166
167 const uint8_t test_data_min[] = {0x00, 0x00, 0x00, 0x00};
168const uint8_t test_data_max[] = {0xff, 0xff, 0xff, 0xff};
169
170def_test__encode__zmq_z85_decode__roundtrip (min, test_data_min)
171 def_test__encode__zmq_z85_decode__roundtrip (max, test_data_max)
172
173#define def_test__decode__zmq_z85_encode__roundtrip(name, param) \
174 def_test__zmq_z85_basename (decode__zmq_z85_encode__roundtrip, name, param)
175
176 const char test_data_regular[] = "r^/rM9M=rMToK)63O8dCvd9D<PY<7iGlC+{BiSnG";
177
178def_test__decode__zmq_z85_encode__roundtrip (regular, test_data_regular)
179
180 int main ()
181{
182 UNITY_BEGIN ();
183 RUN_TEST (test__zmq_z85_encode__valid__success);
184 RUN_TEST (test__zmq_z85_encode__invalid__failure_1);
185 RUN_TEST (test__zmq_z85_encode__invalid__failure_42);
186
187 RUN_TEST (test__zmq_z85_decode__valid__success);
188 RUN_TEST (
189 test__zmq_z85_decode__invalid__failure_indivisble_by_5_multiple_chars);
190 RUN_TEST (test__zmq_z85_decode__invalid__failure_indivisble_by_5_one_char);
191 RUN_TEST (test__zmq_z85_decode__invalid__failure_max);
192 RUN_TEST (test__zmq_z85_decode__invalid__failure_above_limit);
193 RUN_TEST (test__zmq_z85_decode__invalid__failure_char_within);
194 RUN_TEST (test__zmq_z85_decode__invalid__failure_char_adjacent_below);
195 RUN_TEST (test__zmq_z85_decode__invalid__failure_char_adjacent_above);
196
197 RUN_TEST (test__zmq_z85_encode__zmq_z85_decode__roundtrip_min);
198 RUN_TEST (test__zmq_z85_encode__zmq_z85_decode__roundtrip_max);
199
200 RUN_TEST (test__zmq_z85_decode__zmq_z85_encode__roundtrip_regular);
201
202 return UNITY_END ();
203}
204