/ tests / lib / utils.c
utils.c
  1  /*-
  2   * Copyright (c) 2022 Baptiste Daroussin <bapt@FreeBSD.org>
  3   *~
  4   * Redistribution and use in source and binary forms, with or without
  5   * modification, are permitted provided that the following conditions
  6   * are met:
  7   * 1. Redistributions of source code must retain the above copyright
  8   *    notice, this list of conditions and the following disclaimer
  9   *    in this position and unchanged.
 10   * 2. Redistributions in binary form must reproduce the above copyright
 11   *    notice, this list of conditions and the following disclaimer in the
 12   *    documentation and/or other materials provided with the distribution.
 13   *~
 14   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
 15   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 16   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 17   * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
 18   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 19   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 20   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 21   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 23   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24   */
 25  
 26  #include <atf-c.h>
 27  #include <atf-c/macros.h>
 28  #include <err.h>
 29  #include <fcntl.h>
 30  #include <private/utils.h>
 31  #include <private/add.h>
 32  
 33  ATF_TC_WITHOUT_HEAD(hidden_tempfile);
 34  ATF_TC_WITHOUT_HEAD(random_suffix);
 35  ATF_TC_WITHOUT_HEAD(json_escape);
 36  ATF_TC_WITHOUT_HEAD(open_tempdir);
 37  ATF_TC_WITHOUT_HEAD(get_http_auth);
 38  ATF_TC_WITHOUT_HEAD(str_ends_with);
 39  ATF_TC_WITHOUT_HEAD(match_paths);
 40  
 41  ATF_TC_BODY(hidden_tempfile, tc) {
 42  	const char *filename = "plop";
 43  	const char *longfile = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php.gif";
 44  	const char *pathfn = "/tmp/plop";
 45  	const char *pathlongfn = "/tmp/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.php.gif";
 46  	char buf[MAXPATHLEN];
 47  
 48  	hidden_tempfile(buf, MAXPATHLEN, filename);
 49  	ATF_REQUIRE_EQ_MSG(strncmp(buf, ".pkgtemp.plop.", 14), 0, "bad filename '%s'", buf);
 50  	hidden_tempfile(buf, MAXPATHLEN, longfile);
 51  	ATF_REQUIRE_EQ_MSG(strncmp(buf, ".AAA", 4), 0, "bad filename '%s'", buf);
 52  
 53  	hidden_tempfile(buf, MAXPATHLEN, pathfn);
 54  	ATF_REQUIRE_EQ_MSG(strncmp(buf, "/tmp/.pkgtemp.plop.", 19), 0, "bad filename '%s'", buf);
 55  
 56  	hidden_tempfile(buf, MAXPATHLEN, pathlongfn);
 57  	ATF_REQUIRE_EQ_MSG(strncmp(buf, "/tmp/.AAA", 9), 0, "bad filename '%s'", buf);
 58  
 59  
 60  }
 61  ATF_TC_BODY(random_suffix, tc) {
 62  	char buf[14];
 63  
 64  	buf[0] = '\0';
 65  	append_random_suffix(buf, sizeof(buf), 12);
 66  	ATF_REQUIRE_EQ_MSG(strlen(buf), 13, "suffix not long enough %lu", strlen(buf));
 67  	snprintf(buf, sizeof(buf), "filename");
 68  	append_random_suffix(buf, sizeof(buf), 12);
 69  	ATF_REQUIRE_EQ_MSG(strlen(buf), 13, "suffix not long enough %lu", strlen(buf));
 70  }
 71  
 72  ATF_TC_BODY(json_escape, tc) {
 73  	char *m = json_escape("entry1\"\"\\ ");
 74  	ATF_REQUIRE_STREQ_MSG(m, "entry1\\\"\\\"\\\\ ", "Invalid escaping");
 75  	free(m);
 76  }
 77  
 78  ATF_TC_BODY(open_tempdir, tc) {
 79  	struct pkg_add_context ctx = { 0 };
 80  	struct tempdir *t;
 81  	ctx.rootfd = open(getenv("TMPDIR"), O_DIRECTORY);
 82  	ATF_REQUIRE_MSG(ctx.rootfd  != -1, "impossible to open TMPDIR");
 83  	t = open_tempdir(&ctx, "/plop");
 84  	ATF_REQUIRE(t == NULL);
 85  	mkdirat(ctx.rootfd, "usr", 0755);
 86  	t = open_tempdir(&ctx, "/usr/local/directory");
 87  	ATF_REQUIRE(t != NULL);
 88  	ATF_REQUIRE_STREQ(t->name, "/usr/local");
 89  	ATF_REQUIRE_EQ(t->len, strlen("/usr/local"));
 90  	ATF_REQUIRE(strncmp(t->temp, "/usr/.pkgtemp.", 14) == 0);
 91  	ATF_REQUIRE(t->fd != -1);
 92  	close(t->fd);
 93  	free(t);
 94  	t = open_tempdir(&ctx, "/nousr/local/directory");
 95  	ATF_REQUIRE(t != NULL);
 96  	ATF_REQUIRE_STREQ(t->name, "/nousr");
 97  	ATF_REQUIRE_EQ(t->len, strlen("/nousr"));
 98  	ATF_REQUIRE(strncmp(t->temp, "/.pkgtemp.", 10) == 0);
 99  	ATF_REQUIRE(t->fd != -1);
100  	close(t->fd);
101  	free(t);
102  	mkdirat(ctx.rootfd, "dir", 0755);
103  	/* a file in the path */
104  	close(openat(ctx.rootfd, "dir/file1", O_CREAT|O_WRONLY, 0644));
105  	t = open_tempdir(&ctx, "/dir/file1/test");
106  	ATF_REQUIRE(t != NULL);
107  	ATF_REQUIRE_STREQ(t->name, "/dir/file1");
108  	ATF_REQUIRE_EQ(t->len, strlen("/dir/file1"));
109  	ATF_REQUIRE(strncmp(t->temp, "/dir/.pkgtemp.", 14) == 0);
110  	ATF_REQUIRE(t->fd != -1);
111  	close(t->fd);
112  	free(t);
113  }
114  
115  ATF_TC_BODY(get_http_auth, tc) {
116  	unsetenv("HTTP_AUTH");
117  	ATF_REQUIRE(get_http_auth() == NULL);
118  	setenv("HTTP_AUTH", "plop", 1);
119  	ATF_REQUIRE(get_http_auth() == NULL);
120  
121  	setenv("HTTP_AUTH", "basic:any", 1);
122  	ATF_REQUIRE(get_http_auth() == NULL);
123  
124  	setenv("HTTP_AUTH", "basic:any:user", 1);
125  	ATF_REQUIRE(get_http_auth() == NULL);
126  
127  	setenv("HTTP_AUTH", "basic:any:user:passwd", 1);
128  	ATF_REQUIRE_STREQ(get_http_auth(), "user:passwd");
129  }
130  
131  ATF_TC_BODY(str_ends_with, tc) {
132  	ATF_REQUIRE(str_ends_with(NULL, NULL));
133  	ATF_REQUIRE(!str_ends_with(NULL, "end"));
134  	ATF_REQUIRE(!str_ends_with("a", "end"));
135  	ATF_REQUIRE(str_ends_with("end", "end"));
136  	ATF_REQUIRE(str_ends_with("backend", "end"));
137  }
138  
139  ATF_TC_BODY(match_paths, tc) {
140  	const char *paths[] = {
141  		"////",
142  		"/foo1",
143  		"/foo2/",
144  		"////foo3/bar",
145  		"/foo4//bar",
146  		"/foo5//////bar",
147  		"//foo6//bar/",
148  		"/foo7//////bar/",
149  		"////foo8//bar///",
150  		NULL,
151  	};
152  
153  	ucl_object_t *list = ucl_object_typed_new(UCL_ARRAY);
154  	for (size_t i = 0; paths[i] != NULL; i++) {
155  		ucl_array_append(list, ucl_object_fromstring_common(paths[i], 0, 0));
156  	}
157  
158  	ATF_REQUIRE(pkg_match_paths_list(list, "/target.so"));
159  	ATF_REQUIRE(pkg_match_paths_list(list, "/foo1/whatever"));
160  	ATF_REQUIRE(pkg_match_paths_list(list, "/foo2/thing.txt"));
161  	ATF_REQUIRE(pkg_match_paths_list(list, "/foo3/bar/baz.so.1.1.1"));
162  	ATF_REQUIRE(pkg_match_paths_list(list, "////foo4//bar/thingy"));
163  	ATF_REQUIRE(pkg_match_paths_list(list, "/foo5//////bar/whatisit"));
164  	ATF_REQUIRE(pkg_match_paths_list(list, "/foo6//bar/afile"));
165  	ATF_REQUIRE(pkg_match_paths_list(list, "/foo7//////bar/foooo"));
166  	ATF_REQUIRE(pkg_match_paths_list(list, "/foo8//bar///other"));
167  
168  	ATF_REQUIRE(!pkg_match_paths_list(list, "/notinpath/target.so"));
169  	ATF_REQUIRE(!pkg_match_paths_list(list, "//////notinpath////other.so.1"));
170  	ATF_REQUIRE(!pkg_match_paths_list(list, "/a/b/c/d/e/f/g"));
171  }
172  
173  ATF_TP_ADD_TCS(tp)
174  {
175  	ATF_TP_ADD_TC(tp, hidden_tempfile);
176  	ATF_TP_ADD_TC(tp, random_suffix);
177  	ATF_TP_ADD_TC(tp, json_escape);
178  	ATF_TP_ADD_TC(tp, open_tempdir);
179  	ATF_TP_ADD_TC(tp, get_http_auth);
180  	ATF_TP_ADD_TC(tp, str_ends_with);
181  	ATF_TP_ADD_TC(tp, match_paths);
182  
183  	return (atf_no_error());
184  }