1 /* check-sources:disable-copyright-check */
2 /* unit test the code in droplet.c */
3 #include <sys/types.h>
4 #include <limits.h>
5 #include <stdio.h>
6 #include <unistd.h>
7 #include <stdlib.h>
8 #include <errno.h>
9 #include <check.h>
10 #include <droplet.h>
11 
12 #include "utest_main.h"
13 
START_TEST(status_str_test)14 START_TEST(status_str_test)
15 {
16   dpl_assert_str_eq("DPL_SUCCESS", dpl_status_str(0));
17   dpl_assert_str_eq("DPL_SUCCESS", dpl_status_str(DPL_SUCCESS));
18   dpl_assert_str_eq("DPL_FAILURE", dpl_status_str(DPL_FAILURE));
19   /* lots of others, just try one */
20   dpl_assert_str_eq("DPL_ECONNECT", dpl_status_str(DPL_ECONNECT));
21   /* we get a non-null string when passing completely bogus error codes */
22   dpl_assert_ptr_not_null(dpl_status_str(3000));
23   dpl_assert_ptr_not_null(dpl_status_str(-3000));
24 }
25 END_TEST
26 
START_TEST(init_test)27 START_TEST(init_test)
28 {
29   dpl_init();
30   dpl_free();
31 }
32 END_TEST
33 
START_TEST(option_test)34 START_TEST(option_test)
35 {
36   dpl_status_t r;
37   dpl_option_t opt;
38   dpl_option_t* o2;
39 
40   /* the API has no initialiser macro or dpl_option_new() */
41   memset(&opt, 0xff, sizeof(opt));
42 
43   /* testcases where parsing fails */
44 #define TESTCASE(str, err)           \
45   {                                  \
46     r = dpl_parse_option(str, &opt); \
47     dpl_assert_int_eq(err, r);       \
48   }
49 
50   /* colons are necessary (which is dumb, but there it is) */
51   TESTCASE("lazy", DPL_EINVAL);
52   /* a bogus option name fails cleanly */
53   TESTCASE("i_am_so_bogus:", DPL_EINVAL);
54 
55 #undef TESTCASE
56   /* testcases where parsing succeeds */
57 #define TESTCASE(str, maskval, expvers, forvers)  \
58   r = dpl_parse_option(str, &opt);                \
59   dpl_assert_int_eq(DPL_SUCCESS, r);              \
60   dpl_assert_int_eq(maskval, opt.mask);           \
61   dpl_assert_str_eq(expvers, opt.expect_version); \
62   dpl_assert_str_eq(forvers, opt.force_version);  \
63   o2 = dpl_option_dup(&opt);                      \
64   dpl_assert_int_eq(maskval, o2->mask);           \
65   dpl_assert_str_eq(expvers, o2->expect_version); \
66   dpl_assert_str_eq(forvers, o2->force_version);  \
67   dpl_option_free(o2)
68 
69   /* an empty string is a valid set of options */
70   TESTCASE("", 0, "", "");
71   /* run through all the options to make sure they are parsed correctly */
72   TESTCASE("lazy:", DPL_OPTION_LAZY, "", "");
73   TESTCASE("http_compat:", DPL_OPTION_HTTP_COMPAT, "", "");
74   TESTCASE("raw:", DPL_OPTION_RAW, "", "");
75   TESTCASE("append_metadata:", DPL_OPTION_APPEND_METADATA, "", "");
76   TESTCASE("consistent:", DPL_OPTION_CONSISTENT, "", "");
77   TESTCASE("expect_version:123", DPL_OPTION_EXPECT_VERSION, "123", "");
78   TESTCASE("force_version:123", DPL_OPTION_FORCE_VERSION, "", "123");
79   /* two options separated by various separators */
80   TESTCASE("lazy: http_compat:", DPL_OPTION_LAZY | DPL_OPTION_HTTP_COMPAT, "",
81            "");
82   TESTCASE("lazy:,http_compat:", DPL_OPTION_LAZY | DPL_OPTION_HTTP_COMPAT, "",
83            "");
84   TESTCASE("lazy:;http_compat:", DPL_OPTION_LAZY | DPL_OPTION_HTTP_COMPAT, "",
85            "");
86   /* many options */
87   TESTCASE("lazy: http_compat: raw: append_metadata: consistent:",
88            DPL_OPTION_LAZY | DPL_OPTION_HTTP_COMPAT | DPL_OPTION_RAW
89                | DPL_OPTION_APPEND_METADATA | DPL_OPTION_CONSISTENT,
90            "", "");
91   /* order doesn't matter */
92   TESTCASE("http_compat: lazy:", DPL_OPTION_LAZY | DPL_OPTION_HTTP_COMPAT, "",
93            "");
94   TESTCASE("append_metadata: http_compat: raw: consistent: lazy:",
95            DPL_OPTION_LAZY | DPL_OPTION_HTTP_COMPAT | DPL_OPTION_RAW
96                | DPL_OPTION_APPEND_METADATA | DPL_OPTION_CONSISTENT,
97            "", "");
98 
99 #undef TESTCASE
100 }
101 END_TEST
102 
START_TEST(condition_test)103 START_TEST(condition_test)
104 {
105   dpl_status_t r;
106   int i;
107   dpl_condition_t cond;
108   dpl_condition_t* c2;
109 
110   /* the API has no initialiser macro or dpl_condition_new() */
111   memset(&cond, 0xff, sizeof(cond));
112 
113   /* testcases where parsing fails */
114 #define TESTCASE(str, err)               \
115   {                                      \
116     r = dpl_parse_condition(str, &cond); \
117     dpl_assert_int_eq(err, r);           \
118   }
119 
120   /* colons are necessary (which is dumb, but there it is) */
121   TESTCASE("if-match", DPL_EINVAL);
122   /* a bogus option name fails cleanly */
123   TESTCASE("i_am_so_bogus:", DPL_EINVAL);
124   /* an etag which is too long */
125   TESTCASE(
126       "if-none-match:"
127       "ecf3245105b18821eda700c279ba9ae39af72c169574ea47e3c37037744fb444710f4f31"
128       "d655894305f380b0a8c1aa83",
129       DPL_EINVAL);
130   /* an invalid time string */
131   TESTCASE("if-modified-since:356-Flubuary-20789", DPL_EINVAL);
132   /* too many conditions */
133   TESTCASE(
134       "if-match:a if-match:b if-match:c if-match:d if-match:e "
135       "if-match:f if-match:g if-match:h if-match:i if-match:j "
136       "if-match:k",
137       DPL_ENAMETOOLONG);
138 
139 #undef TESTCASE
140   /* testcases where parsing succeeds */
141 #define TESTCASE(str, ...)                                 \
142   {                                                        \
143     const dpl_condition_one_t _e[] = {__VA_ARGS__};        \
144     int _n = sizeof(_e) / sizeof(_e[0]);                   \
145     r = dpl_parse_condition(str, &cond);                   \
146     dpl_assert_int_eq(DPL_SUCCESS, r);                     \
147     dpl_assert_int_eq(_n, cond.n_conds);                   \
148     for (i = 0; i < _n; i++) {                             \
149       dpl_assert_int_eq(_e[i].type, cond.conds[i].type);   \
150       dpl_assert_int_eq(_e[i].time, cond.conds[i].time);   \
151       dpl_assert_str_eq(_e[i].etag, cond.conds[i].etag);   \
152     }                                                      \
153     c2 = dpl_condition_dup(&cond);                         \
154     dpl_assert_ptr_not_null(c2);                           \
155     dpl_assert_int_eq(0, memcmp(c2, &cond, sizeof(cond))); \
156     dpl_condition_free(c2);                                \
157   }
158 
159   /* an empty string is a valid set of conditions */
160   TESTCASE("");
161   /* run through all the conditions to make sure they are parsed correctly */
162   TESTCASE("if-match:5eaebe6fcda83fa5c9904836314df05d",
163            {.type = DPL_CONDITION_IF_MATCH,
164             .etag = "5eaebe6fcda83fa5c9904836314df05d"});
165   TESTCASE("if-none-match:3381508f73d74f53a76a8d748f4b2a6d",
166            {.type = DPL_CONDITION_IF_NONE_MATCH,
167             .etag = "3381508f73d74f53a76a8d748f4b2a6d"});
168   TESTCASE("if-modified-since:15-Oct-2010()03:19:52()+1100",
169            {.type = DPL_CONDITION_IF_MODIFIED_SINCE, .time = 1287073192L});
170   TESTCASE("if-unmodified-since:5-Oct-2010()03:19:52()+1100",
171            {.type = DPL_CONDITION_IF_UNMODIFIED_SINCE, .time = 1286209192L});
172   /* multiple conditions */
173   TESTCASE("if-match:a if-match:b",
174            {.type = DPL_CONDITION_IF_MATCH, .etag = "a"},
175            {.type = DPL_CONDITION_IF_MATCH, .etag = "b"});
176   TESTCASE("if-match:a if-none-match:b if-match:c",
177            {.type = DPL_CONDITION_IF_MATCH, .etag = "a"},
178            {.type = DPL_CONDITION_IF_NONE_MATCH, .etag = "b"},
179            {.type = DPL_CONDITION_IF_MATCH, .etag = "c"});
180 
181 #undef TESTCASE
182 }
183 END_TEST
184 
droplet_suite()185 Suite* droplet_suite()
186 {
187   Suite* s = suite_create("droplet");
188   TCase* t = tcase_create("base");
189   tcase_add_test(t, status_str_test);
190   tcase_add_test(t, init_test);
191   tcase_add_test(t, option_test);
192   tcase_add_test(t, condition_test);
193   suite_add_tcase(s, t);
194   return s;
195 }
196