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 
setUp()33 void setUp ()
34 {
35 }
36 
tearDown()37 void tearDown ()
38 {
39 }
40 
41 // Test vector: rfc.zeromq.org/spec:32/Z85
test__zmq_z85_encode__valid__success()42 void 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.
test__zmq_z85_encode__invalid__failure(size_t size_)58 void 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
test__zmq_z85_decode__valid__success()66 void 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.
81 template <size_t SIZE>
test__zmq_z85_decode__invalid__failure(const char (& encoded_)[SIZE])82 void 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
92 template <size_t SIZE>
test__zmq_z85_encode__zmq_z85_decode__roundtrip(const uint8_t (& test_data_)[SIZE])93 void 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     const char *const 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     const uint8_t *const res2 =
102       zmq_z85_decode (test_data_decoded, test_data_z85);
103     TEST_ASSERT_NOT_NULL (res2);
104 
105     TEST_ASSERT_EQUAL_UINT8_ARRAY (test_data_, test_data_decoded, SIZE);
106 }
107 
108 // call zmq_z85_encode, then zmq_z85_decode, and compare the results with the original
109 template <size_t SIZE>
test__zmq_z85_decode__zmq_z85_encode__roundtrip(const char (& test_data_)[SIZE])110 void test__zmq_z85_decode__zmq_z85_encode__roundtrip (
111   const char (&test_data_)[SIZE])
112 {
113     const size_t decoded_size = (SIZE - 1) * 4 / 5;
114     uint8_t test_data_decoded[decoded_size];
115     const uint8_t *const res1 = zmq_z85_decode (test_data_decoded, test_data_);
116     TEST_ASSERT_NOT_NULL (res1);
117 
118     char test_data_z85[SIZE];
119     const char *const res2 =
120       zmq_z85_encode (test_data_z85, test_data_decoded, decoded_size);
121     TEST_ASSERT_NOT_NULL (res2);
122 
123     TEST_ASSERT_EQUAL_UINT8_ARRAY (test_data_, test_data_z85, SIZE);
124 }
125 
126 #define def_test__zmq_z85_basename(basename, name, param)                      \
127     void test__zmq_z85_##basename##_##name ()                                  \
128     {                                                                          \
129         test__zmq_z85_##basename (param);                                      \
130     }
131 
132 #define def_test__zmq_z85_encode__invalid__failure(name, param)                \
133     def_test__zmq_z85_basename (encode__invalid__failure, name, param)
134 
135 def_test__zmq_z85_encode__invalid__failure (1, 1)
136   def_test__zmq_z85_encode__invalid__failure (42, 42)
137 
138 #define def_test__zmq_z85_decode__invalid__failure(name, param)                \
139     def_test__zmq_z85_basename (decode__invalid__failure, name, param)
140 
141   // String length must be evenly divisible by 5 or must fail with EINVAL.
142   def_test__zmq_z85_decode__invalid__failure (indivisble_by_5_multiple_chars,
143                                               "01234567")
144     def_test__zmq_z85_decode__invalid__failure (indivisble_by_5_one_char, "0")
145 
146   // decode invalid data with the maximum representable value
147   def_test__zmq_z85_decode__invalid__failure (max, "#####")
148 
149   // decode invalid data with the minimum value beyond the limit
150   // "%nSc0" is 0xffffffff
151   def_test__zmq_z85_decode__invalid__failure (above_limit, "%nSc1")
152 
153   // decode invalid data with an invalid character in the range of valid
154   // characters
155   def_test__zmq_z85_decode__invalid__failure (char_within, "####\0047")
156 
157   // decode invalid data with an invalid character just below the range of valid
158   // characters
159   def_test__zmq_z85_decode__invalid__failure (char_adjacent_below, "####\0200")
160 
161   // decode invalid data with an invalid character just above the range of valid
162   // characters
163   def_test__zmq_z85_decode__invalid__failure (char_adjacent_above, "####\0037")
164 
165 #define def_test__encode__zmq_z85_decode__roundtrip(name, param)               \
166     def_test__zmq_z85_basename (encode__zmq_z85_decode__roundtrip, name, param)
167 
168     const uint8_t test_data_min[] = {0x00, 0x00, 0x00, 0x00};
169 const uint8_t test_data_max[] = {0xff, 0xff, 0xff, 0xff};
170 
171 def_test__encode__zmq_z85_decode__roundtrip (min, test_data_min)
172   def_test__encode__zmq_z85_decode__roundtrip (max, test_data_max)
173 
174 #define def_test__decode__zmq_z85_encode__roundtrip(name, param)               \
175     def_test__zmq_z85_basename (decode__zmq_z85_encode__roundtrip, name, param)
176 
177     const char test_data_regular[] = "r^/rM9M=rMToK)63O8dCvd9D<PY<7iGlC+{BiSnG";
178 
def_test__decode__zmq_z85_encode__roundtrip(regular,test_data_regular)179 def_test__decode__zmq_z85_encode__roundtrip (regular, test_data_regular)
180 
181   int main ()
182 {
183     UNITY_BEGIN ();
184     RUN_TEST (test__zmq_z85_encode__valid__success);
185     RUN_TEST (test__zmq_z85_encode__invalid__failure_1);
186     RUN_TEST (test__zmq_z85_encode__invalid__failure_42);
187 
188     RUN_TEST (test__zmq_z85_decode__valid__success);
189     RUN_TEST (
190       test__zmq_z85_decode__invalid__failure_indivisble_by_5_multiple_chars);
191     RUN_TEST (test__zmq_z85_decode__invalid__failure_indivisble_by_5_one_char);
192     RUN_TEST (test__zmq_z85_decode__invalid__failure_max);
193     RUN_TEST (test__zmq_z85_decode__invalid__failure_above_limit);
194     RUN_TEST (test__zmq_z85_decode__invalid__failure_char_within);
195     RUN_TEST (test__zmq_z85_decode__invalid__failure_char_adjacent_below);
196     RUN_TEST (test__zmq_z85_decode__invalid__failure_char_adjacent_above);
197 
198     RUN_TEST (test__zmq_z85_encode__zmq_z85_decode__roundtrip_min);
199     RUN_TEST (test__zmq_z85_encode__zmq_z85_decode__roundtrip_max);
200 
201     RUN_TEST (test__zmq_z85_decode__zmq_z85_encode__roundtrip_regular);
202 
203     return UNITY_END ();
204 }
205