From 572e6fb63fb9570b429d39c5f52a4b7025fd15ee Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 6 Jul 2022 15:07:51 -0400 Subject: Avoid incorrect use of mkstemp in tests This was an overly hasty switch from race-prone alternatives to mkstemp, but it did not actually account for the fact that mkstemp creates the file. This resulted in leaking the file handle, and trying to open it twice, which made the tests fail on Windows/MinGW. --- test/test.lv2/test.c | 72 +++++++++++++++++++++++++++++++++++++++++----------- test/test_util.c | 37 +++++++++++---------------- 2 files changed, 72 insertions(+), 37 deletions(-) (limited to 'test') diff --git a/test/test.lv2/test.c b/test/test.lv2/test.c index 2be34b4..1dc7076 100644 --- a/test/test.lv2/test.c +++ b/test/test.lv2/test.c @@ -1,6 +1,6 @@ /* Lilv Test Plugin - Copyright 2011-2019 David Robillard + Copyright 2011-2022 David Robillard Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -22,9 +22,9 @@ #include "lv2/state/state.h" #include "lv2/urid/urid.h" -#ifdef _MSC_VER -# include -# define mkstemp(pat) _mktemp(pat) +#ifdef _WIN32 +# define _WIN32_LEAN_AND_MEAN +# include #endif #include @@ -34,8 +34,6 @@ #define TEST_URI "http://example.org/lilv-test-plugin" -#define TMP_TEMPLATE "lilv_testXXXXXX" - enum { TEST_INPUT = 0, TEST_OUTPUT = 1, TEST_CONTROL = 2 }; typedef struct { @@ -46,7 +44,7 @@ typedef struct { LV2_URID atom_Float; } uris; - char tmp_file_path[sizeof(TMP_TEMPLATE)]; + char* tmp_dir_path; char* rec_file_path; FILE* rec_file; @@ -55,6 +53,35 @@ typedef struct { unsigned num_runs; } Test; +static char* +temp_directory_path(void) +{ +#ifdef _WIN32 + const DWORD len = GetTempPath(0, NULL); + char* const buf = (char*)calloc(len, 1); + if (GetTempPath(len, buf) == 0) { + free(buf); + return NULL; + } + + return buf; +#else + const char* const tmpdir = getenv("TMPDIR"); + if (tmpdir) { + const size_t tmpdir_len = strlen(tmpdir); + char* const result = (char*)calloc(tmpdir_len + 1, 1); + + memcpy(result, tmpdir, tmpdir_len + 1); + return result; + } + + char* const result = (char*)calloc(6, 1); + + memcpy(result, "/tmp/", 6); + return result; +#endif +} + static void cleanup(LV2_Handle instance) { @@ -67,6 +94,7 @@ cleanup(LV2_Handle instance) test->free_path->free_path(test->free_path->handle, test->rec_file_path); } + free(test->tmp_dir_path); free(instance); } @@ -104,8 +132,7 @@ instantiate(const LV2_Descriptor* descriptor, return NULL; } - strncpy(test->tmp_file_path, TMP_TEMPLATE, strlen(TMP_TEMPLATE) + 1); - mkstemp(test->tmp_file_path); + test->tmp_dir_path = temp_directory_path(); LV2_State_Make_Path* make_path = NULL; @@ -272,15 +299,30 @@ save(LV2_Handle instance, LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); if (map_path) { - FILE* file = fopen(plugin->tmp_file_path, "w"); + const char* const file_name = "temp_file.txt"; + const size_t file_name_len = strlen(file_name); + const size_t dir_path_len = strlen(plugin->tmp_dir_path); + char* const tmp_file_path = + (char*)calloc(dir_path_len + file_name_len + 1, 1); + + memcpy(tmp_file_path, plugin->tmp_dir_path, dir_path_len); + memcpy(tmp_file_path + dir_path_len, file_name, file_name_len + 1); + + FILE* file = fopen(tmp_file_path, "w"); + if (!file) { + fprintf(stderr, "error: Failed to open file %s\n", tmp_file_path); + free(tmp_file_path); + return LV2_STATE_ERR_UNKNOWN; + } + fprintf(file, "Hello\n"); fclose(file); - char* apath = - map_path->abstract_path(map_path->handle, plugin->tmp_file_path); - char* apath2 = - map_path->abstract_path(map_path->handle, plugin->tmp_file_path); + + char* apath = map_path->abstract_path(map_path->handle, tmp_file_path); + char* apath2 = map_path->abstract_path(map_path->handle, tmp_file_path); + free(tmp_file_path); if (strcmp(apath, apath2)) { - fprintf(stderr, "ERROR: Path %s != %s\n", apath, apath2); + fprintf(stderr, "error: Path %s != %s\n", apath, apath2); } store(callback_data, diff --git a/test/test_util.c b/test/test_util.c index 8c8f36a..c140e34 100644 --- a/test/test_util.c +++ b/test/test_util.c @@ -1,5 +1,5 @@ /* - Copyright 2007-2020 David Robillard + Copyright 2007-2022 David Robillard Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -14,44 +14,30 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define _XOPEN_SOURCE 600 /* for mkstemp */ - #undef NDEBUG -#ifdef _WIN32 -# include "lilv_internal.h" -#endif - #include "../src/filesystem.h" -#ifdef _WIN32 -# include -# define mkstemp(pat) _mktemp(pat) -#endif +#include "lilv/lilv.h" #include #include -#include -#include int main(void) { assert(!lilv_path_canonical(NULL)); - char a_path[16]; - char b_path[16]; - strncpy(a_path, "copy_a_XXXXXX", sizeof(a_path)); - strncpy(b_path, "copy_b_XXXXXX", sizeof(b_path)); - mkstemp(a_path); - mkstemp(b_path); + char* const dir = lilv_create_temporary_directory("lilv_test_util_XXXXXX"); + char* const a_path = lilv_path_join(dir, "copy_a_XXXXXX"); + char* const b_path = lilv_path_join(dir, "copy_b_XXXXXX"); - FILE* fa = fopen(a_path, "w"); - FILE* fb = fopen(b_path, "w"); + FILE* const fa = fopen(a_path, "w"); + FILE* const fb = fopen(b_path, "w"); fprintf(fa, "AA\n"); fprintf(fb, "AB\n"); - fclose(fa); fclose(fb); + fclose(fa); assert(lilv_copy_file("does/not/exist", "copy")); assert(lilv_copy_file(a_path, "not/a/dir/copy")); @@ -63,5 +49,12 @@ main(void) assert(!lilv_file_equals(a_path, "does/not/exist")); assert(!lilv_file_equals("does/not/exist", "/does/not/either")); + assert(!lilv_remove(a_path)); + assert(!lilv_remove(b_path)); + assert(!lilv_remove(dir)); + + lilv_free(b_path); + lilv_free(a_path); + lilv_free(dir); return 0; } -- cgit v1.2.1