diff --git a/.dockerignore b/.dockerignore index 0fad02e7..6e98e90b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,6 +4,7 @@ !docs/man !etc/apache2/renderd-example-map.conf !etc/apache2/tile.load.in +!etc/renderd/renderd.conf.examples !etc/renderd/renderd.conf.in !includes !src diff --git a/Makefile.am b/Makefile.am index 3038fb2a..c416e9f1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,13 @@ bin_PROGRAMS = \ render_list \ render_old \ render_speedtest -noinst_PROGRAMS = gen_tile_test +noinst_PROGRAMS = \ + gen_tile_test \ + renderd_test \ + render_expired_test \ + render_list_test \ + render_old_test \ + render_speedtest_test man_MANS = \ docs/man/renderd.1 \ @@ -57,49 +63,82 @@ render_speedtest_SOURCES = \ src/g_logger.c \ src/protocol_helper.c \ src/render_submit_queue.c \ + src/renderd_config.c \ src/sys_utils.c -render_speedtest_LDADD = $(PTHREAD_CFLAGS) $(GLIB_LIBS) +render_speedtest_LDADD = $(PTHREAD_CFLAGS) $(GLIB_LIBS) $(INIPARSER_LDFLAGS) render_list_SOURCES = \ src/render_list.c \ src/protocol_helper.c \ src/render_submit_queue.c \ + src/renderd_config.c \ src/sys_utils.c \ $(STORE_SOURCES) -render_list_LDADD = $(PTHREAD_CFLAGS) $(STORE_LDFLAGS) +render_list_LDADD = $(PTHREAD_CFLAGS) $(STORE_LDFLAGS) $(INIPARSER_LDFLAGS) render_expired_SOURCES = \ src/render_expired.c \ src/protocol_helper.c \ src/render_submit_queue.c \ + src/renderd_config.c \ src/sys_utils.c \ $(STORE_SOURCES) -render_expired_LDADD = $(PTHREAD_CFLAGS) $(STORE_LDFLAGS) +render_expired_LDADD = $(PTHREAD_CFLAGS) $(STORE_LDFLAGS) $(INIPARSER_LDFLAGS) render_old_SOURCES = \ src/render_old.c \ src/g_logger.c \ src/protocol_helper.c \ src/render_submit_queue.c \ + src/renderd_config.c \ src/store_file_utils.c \ src/sys_utils.c -render_old_LDADD = $(PTHREAD_CFLAGS) $(GLIB_LIBS) +render_old_LDADD = $(PTHREAD_CFLAGS) $(GLIB_LIBS) $(INIPARSER_LDFLAGS) #convert_meta_SOURCES = src/dir_utils.c src/store.c src/convert_meta.c +noinst_LIBRARIES = catch_main.o catch_test_common.o +catch_main_o_SOURCES = tests/catch/catch_main.cpp +catch_test_common_o_SOURCES = tests/catch/catch_test_common.cpp + gen_tile_test_SOURCES = \ tests/gen_tile_test.cpp \ $(renderd_SOURCES) gen_tile_test_CFLAGS = -DMAIN_ALREADY_DEFINED gen_tile_test_CXXFLAGS = $(renderd_CXXFLAGS) -gen_tile_test_LDADD = $(renderd_LDADD) +gen_tile_test_LDADD = $(renderd_LDADD) catch_test_common.o + +renderd_test_SOURCES = \ + tests/renderd_test.cpp +renderd_test_LDADD = $(GLIB_LIBS) catch_main.o catch_test_common.o + +render_expired_test_SOURCES = \ + tests/render_expired_test.cpp +render_expired_test_LDADD = $(GLIB_LIBS) catch_main.o catch_test_common.o + +render_list_test_SOURCES = \ + tests/render_list_test.cpp +render_list_test_LDADD = $(GLIB_LIBS) catch_main.o catch_test_common.o + +render_old_test_SOURCES = \ + tests/render_old_test.cpp +render_old_test_LDADD = $(GLIB_LIBS) catch_main.o catch_test_common.o + +render_speedtest_test_SOURCES = \ + tests/render_speedtest_test.cpp +render_speedtest_test_LDADD = $(GLIB_LIBS) catch_main.o catch_test_common.o CLEANFILES=*.slo mod_tile.la stderr.out src/*.slo src/*.lo src/.libs/* src/*.la COMMA=, -test: gen_tile_test +test: gen_tile_test renderd_test render_expired_test render_list_test render_old_test render_speedtest_test ./gen_tile_test + ./renderd_test + ./render_expired_test + ./render_list_test + ./render_old_test + ./render_speedtest_test all-local: $(APXS) -c $(DEF_LDLIBS) $(AM_CFLAGS) \ diff --git a/docker/centos/stream/Dockerfile.autotools b/docker/centos/stream/Dockerfile.autotools index ef0975fa..141de381 100644 --- a/docker/centos/stream/Dockerfile.autotools +++ b/docker/centos/stream/Dockerfile.autotools @@ -135,7 +135,7 @@ RUN export DESTDIR=/tmp/mod_tile && \ ./autogen.sh && \ ./configure && \ make DESTDIR=${DESTDIR} install install-mod_tile -RUN ./gen_tile_test +RUN make test # Runner FROM quay.io/centos/centos:stream${centos_stream_version} as runner diff --git a/docker/debian/Dockerfile.autotools b/docker/debian/Dockerfile.autotools index d6bb0e90..21b689a6 100644 --- a/docker/debian/Dockerfile.autotools +++ b/docker/debian/Dockerfile.autotools @@ -36,7 +36,7 @@ RUN export DESTDIR=/tmp/mod_tile && \ ./autogen.sh && \ ./configure && \ make DESTDIR=${DESTDIR} install install-mod_tile -RUN ./gen_tile_test +RUN make test # Runner FROM debian:${debian_version} as runner diff --git a/docker/ubuntu/Dockerfile.autotools b/docker/ubuntu/Dockerfile.autotools index 285ea8e9..6367b768 100644 --- a/docker/ubuntu/Dockerfile.autotools +++ b/docker/ubuntu/Dockerfile.autotools @@ -36,7 +36,7 @@ RUN export DESTDIR=/tmp/mod_tile && \ ./autogen.sh && \ ./configure && \ make DESTDIR=${DESTDIR} install install-mod_tile -RUN ./gen_tile_test +RUN make test # Runner FROM ubuntu:${ubuntu_version} as runner diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6e507333..e8abc21b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -87,9 +87,11 @@ set(render_expired_SRCS protocol_helper.c render_expired.c render_submit_queue.c + renderd_config.c ) set(render_expired_LIBS ${COMMON_LIBRARIES} + ${INIPARSER_LIBRARIES} ${STORE_LIBRARIES} ) add_executable(render_expired ${render_expired_SRCS}) @@ -107,9 +109,11 @@ set(render_list_SRCS protocol_helper.c render_list.c render_submit_queue.c + renderd_config.c ) set(render_list_LIBS ${COMMON_LIBRARIES} + ${INIPARSER_LIBRARIES} ${STORE_LIBRARIES} ) add_executable(render_list ${render_list_SRCS}) @@ -126,10 +130,12 @@ set(render_old_SRCS protocol_helper.c render_old.c render_submit_queue.c + renderd_config.c store_file_utils.c ) set(render_old_LIBS ${COMMON_LIBRARIES} + ${INIPARSER_LIBRARIES} ) add_executable(render_old ${render_old_SRCS}) target_link_libraries(render_old ${render_old_LIBS}) @@ -145,9 +151,11 @@ set(render_speedtest_SRCS protocol_helper.c render_speedtest.cpp render_submit_queue.c + renderd_config.c ) set(render_speedtest_LIBS ${COMMON_LIBRARIES} + ${INIPARSER_LIBRARIES} ) add_executable(render_speedtest ${render_speedtest_SRCS}) target_link_libraries(render_speedtest ${render_speedtest_LIBS}) @@ -195,6 +203,7 @@ if(ENABLE_TESTS) #----------------------------------------------------------------------------- set(gen_tile_test_SRCS + $ ${renderd_SRCS} ${PROJECT_SOURCE_DIR}/tests/gen_tile_test.cpp ) diff --git a/src/render_expired.c b/src/render_expired.c index 9cf2abea..5f58df74 100644 --- a/src/render_expired.c +++ b/src/render_expired.c @@ -15,32 +15,22 @@ * along with this program; If not, see http://www.gnu.org/licenses/. */ +#include +#include +#include #include #include -#include -#include -#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include - -#include +#include -#include "g_logger.h" -#include "protocol.h" #include "config.h" +#include "g_logger.h" #include "render_config.h" -#include "store.h" #include "render_submit_queue.h" - -const char * tile_dir_default = RENDERD_TILE_DIR; +#include "renderd_config.h" +#include "store.h" // macros handling our tile marking arrays (these are essentially bit arrays // that have one bit for each tile on the repsective zoom level; since we only @@ -48,11 +38,10 @@ const char * tile_dir_default = RENDERD_TILE_DIR; // we'd still only use 4^17 bits = 2 GB RAM (plus a little for the lower zoom // levels) - this saves us the hassle of working with a tree structure. -#define TILE_REQUESTED(z,x,y) \ - (tile_requested[z][((x)*twopow[z]+(y))/(8*sizeof(int))]>>(((x)*twopow[z]+(y))%(8*sizeof(int))))&0x01 -#define SET_TILE_REQUESTED(z,x,y) \ - tile_requested[z][((x)*twopow[z]+(y))/(8*sizeof(int))] |= (0x01 << (((x)*twopow[z]+(y))%(8*sizeof(int)))); - +#define TILE_REQUESTED(z, x, y) \ + (tile_requested[z][((x)*twopow[z] + (y)) / (8 * sizeof(int))] >> (((x)*twopow[z] + (y)) % (8 * sizeof(int)))) & 0x01 +#define SET_TILE_REQUESTED(z, x, y) \ + tile_requested[z][((x)*twopow[z] + (y)) / (8 * sizeof(int))] |= (0x01 << (((x)*twopow[z] + (y)) % (8 * sizeof(int)))); #ifndef METATILE #warning("render_expired not implemented for non-metatile mode. Feel free to submit fix") @@ -70,45 +59,56 @@ unsigned int **tile_requested; // for base 2 unsigned long long twopow[MAX_ZOOM]; -static int minZoom = 0; -static int maxZoom = 18; -static int verbose = 0; -static int maxLoad = MAX_LOAD_OLD; - void display_rate(struct timeval start, struct timeval end, int num) { int d_s, d_us; float sec; - d_s = end.tv_sec - start.tv_sec; + d_s = end.tv_sec - start.tv_sec; d_us = end.tv_usec - start.tv_usec; sec = d_s + d_us / 1000000.0; - printf("Rendered %d tiles in %.2f seconds (%.2f tiles/s)\n", num, sec, num / sec); - fflush(NULL); + g_logger(G_LOG_LEVEL_MESSAGE, "\tRendered %d tiles in %.2f seconds (%.2f tiles/s)", num, sec, num / sec); } - - int main(int argc, char **argv) { - char *spath = strdup(RENDERD_SOCKET); + const char *config_file_name_default = RENDERD_CONFIG; const char *mapname_default = XMLCONFIG_DEFAULT; + const char *socketname_default = RENDERD_SOCKET; + const char *tile_dir_default = RENDERD_TILE_DIR; + int max_load_default = MAX_LOAD_OLD; + int max_zoom_default = 18; + int min_zoom_default = 0; + int num_threads_default = 1; + + const char *config_file_name = config_file_name_default; const char *mapname = mapname_default; + const char *socketname = socketname_default; const char *tile_dir = tile_dir_default; + int max_load = max_load_default; + int max_zoom = max_zoom_default; + int min_zoom = min_zoom_default; + int num_threads = num_threads_default; + + int config_file_name_passed = 0; + int mapname_passed = 0; + int socketname_passed = 0; + int tile_dir_passed = 0; + int max_load_passed = 0; + int max_zoom_passed = 0; + int min_zoom_passed = 0; + int num_threads_passed = 0; + int x, y, z; struct timeval start, end; int num_render = 0, num_all = 0, num_read = 0, num_ignore = 0, num_unlink = 0, num_touch = 0; - int c; - int numThreads = 1; - int deleteFrom = -1; - int touchFrom = -1; + int deleteFrom = -1, touchFrom = -1; int doRender = 0; int progress = 1; - int i; - struct storage_backend * store; - char name[PATH_MAX]; + int verbose = 0; + struct storage_backend *store; // excess_zoomlevels is how many zoom levels at the large end // we can ignore because their tiles will share one meta tile. @@ -126,16 +126,17 @@ int main(int argc, char **argv) while (1) { int option_index = 0; static struct option long_options[] = { + {"config", required_argument, 0, 'c'}, {"delete-from", required_argument, 0, 'd'}, {"map", required_argument, 0, 'm'}, {"max-load", required_argument, 0, 'l'}, {"max-zoom", required_argument, 0, 'Z'}, {"min-zoom", required_argument, 0, 'z'}, + {"no-progress", no_argument, 0, 'N'}, {"num-threads", required_argument, 0, 'n'}, {"socket", required_argument, 0, 's'}, {"tile-dir", required_argument, 0, 't'}, {"touch-from", required_argument, 0, 'T'}, - {"no-progress", no_argument, 0, 'N'}, {"verbose", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, @@ -143,97 +144,89 @@ int main(int argc, char **argv) {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "d:m:l:Z:z:n:s:t:T:vhV", long_options, &option_index); + int c = getopt_long(argc, argv, "c:d:m:l:Z:z:Nn:s:t:T:vhV", long_options, &option_index); if (c == -1) { break; } switch (c) { - case 's': /* -s, --socket */ - spath = strdup(optarg); - break; - - case 't': /* -t, --tile-dir */ - tile_dir = strdup(optarg); - break; + case 'c': /* -c, --config */ + config_file_name = strndup(optarg, PATH_MAX); + config_file_name_passed = 1; - case 'm': /* -m, --map */ - mapname = strdup(optarg); - break; - - case 'n': /* -n, --num-threads */ - numThreads = atoi(optarg); + struct stat buffer; - if (numThreads <= 0) { - fprintf(stderr, "Invalid number of threads, must be at least 1\n"); + if (stat(config_file_name, &buffer) != 0) { + g_logger(G_LOG_LEVEL_CRITICAL, "Config file '%s' does not exist, please specify a valid file", config_file_name); return 1; } break; - case 'd': /* -d, --delete-from */ - deleteFrom = atoi(optarg); - - if (deleteFrom < 0 || deleteFrom > MAX_ZOOM) { - fprintf(stderr, "Invalid 'delete-from' zoom, must be between 0 and %d\n", MAX_ZOOM); - return 1; - } - + case 'd': /* -d, --delete-from */ + deleteFrom = min_max_int_opt(optarg, "delete-from", 0, MAX_ZOOM); break; - case 'T': /* -T, --touch-from */ - touchFrom = atoi(optarg); - - if (touchFrom < 0 || touchFrom > MAX_ZOOM) { - fprintf(stderr, "Invalid 'touch-from' zoom, must be between 0 and %d\n", MAX_ZOOM); - return 1; - } - + case 'm': /* -m, --map */ + mapname = strndup(optarg, XMLCONFIG_MAX); + mapname_passed = 1; break; - case 'z': /* -z, --min-zoom */ - minZoom = atoi(optarg); + case 'l': /* -l, --max-load */ + max_load = min_max_int_opt(optarg, "maximum load", 0, -1); + max_load_passed = 1; + break; - if (minZoom < 0 || minZoom > MAX_ZOOM) { - fprintf(stderr, "Invalid minimum zoom selected, must be between 0 and %d\n", MAX_ZOOM); - return 1; - } + case 'Z': /* -Z, --max-zoom */ + max_zoom = min_max_int_opt(optarg, "maximum zoom", 0, MAX_ZOOM); + max_zoom_passed = 1; + break; + case 'z': /* -z, --min-zoom */ + min_zoom = min_max_int_opt(optarg, "minimum zoom", 0, MAX_ZOOM); + min_zoom_passed = 1; break; - case 'Z': /* -Z, --max-zoom */ - maxZoom = atoi(optarg); + case 'N': /* -N, --no-progress */ + progress = 0; + break; - if (maxZoom < 0 || maxZoom > MAX_ZOOM) { - fprintf(stderr, "Invalid maximum zoom selected, must be between 0 and %d\n", MAX_ZOOM); - return 1; - } + case 'n': /* -n, --num-threads */ + num_threads = min_max_int_opt(optarg, "number of threads", 1, -1); + num_threads_passed = 1; + break; + case 's': /* -s, --socket */ + socketname = strndup(optarg, PATH_MAX); + socketname_passed = 1; break; - case 'l': /* -l, --max-load */ - maxLoad = atoi(optarg); + case 't': /* -t, --tile-dir */ + tile_dir = strndup(optarg, PATH_MAX); + tile_dir_passed = 1; break; - case 'N': /* --no-progress */ - progress = 0; + case 'T': /* -T, --touch-from */ + touchFrom = min_max_int_opt(optarg, "touch-from", 0, MAX_ZOOM); break; - case 'v': /* -v, --verbose */ + case 'v': /* -v, --verbose */ verbose = 1; break; - case 'h': /* -h, --help */ + case 'h': /* -h, --help */ fprintf(stderr, "Usage: render_expired [OPTION] ...\n"); + fprintf(stderr, " -c, --config=CONFIG specify the renderd config file (default is off)\n"); fprintf(stderr, " -d, --delete-from=ZOOM when expiring tiles of ZOOM or higher, delete them instead of re-rendering (default is off)\n"); - fprintf(stderr, " -m, --map=MAP render tiles in this map (defaults to '" XMLCONFIG_DEFAULT "')\n"); - fprintf(stderr, " -n, --num-threads=N the number of parallel request threads (default 1)\n"); - fprintf(stderr, " -s, --socket=SOCKET|HOSTNAME:PORT unix domain socket name or hostname and port for contacting renderd\n"); - fprintf(stderr, " -t, --tile-dir tile cache directory (defaults to '" RENDERD_TILE_DIR "')\n"); + fprintf(stderr, " -m, --map=MAP render tiles in this map (default is '%s')\n", mapname_default); + fprintf(stderr, " -l, --max-load=LOAD sleep if load is this high (default is '%d')\n", max_load_default); + fprintf(stderr, " -n, --num-threads=N the number of parallel request threads (default is '%d')\n", num_threads_default); + fprintf(stderr, " -s, --socket=SOCKET|HOSTNAME:PORT unix domain socket name or hostname and port for contacting renderd (default is '%s')\n", socketname_default); + fprintf(stderr, " -t, --tile-dir=TILE_DIR tile cache directory (default is '%s')\n", tile_dir_default); fprintf(stderr, " -T, --touch-from=ZOOM when expiring tiles of ZOOM or higher, touch them instead of re-rendering (default is off)\n"); - fprintf(stderr, " -Z, --max-zoom=ZOOM filter input to only render tiles less than or equal to this zoom level (default is %d)\n", 18); - fprintf(stderr, " -z, --min-zoom=ZOOM filter input to only render tiles greater or equal to this zoom level (default is 0)\n"); + fprintf(stderr, " -Z, --max-zoom=ZOOM filter input to only render tiles less than or equal to this zoom level (default is '%d')\n", max_zoom_default); + fprintf(stderr, " -z, --min-zoom=ZOOM filter input to only render tiles greater than or equal to this zoom level (default is '%d')\n", min_zoom_default); fprintf(stderr, "\n"); fprintf(stderr, " -h, --help display this help and exit\n"); fprintf(stderr, " -V, --version display the version number and exit\n"); @@ -246,71 +239,117 @@ int main(int argc, char **argv) fprintf(stderr, " 1/0/0\n"); fprintf(stderr, " 1/1/0\n"); fprintf(stderr, "The above would cause all 4 tiles at zoom 1 to be rendered\n"); - exit(0); + return 0; - case 'V': + case 'V': /* -V, --version */ fprintf(stdout, "%s\n", VERSION); - exit(0); + return 0; default: - fprintf(stderr, "unhandled char '%c'\n", c); - exit(1); + g_logger(G_LOG_LEVEL_CRITICAL, "unhandled char '%c'", c); + return 1; } } - if (maxZoom < minZoom) { - fprintf(stderr, "Invalid zoom range, max zoom must be greater or equal to minimum zoom\n"); + if (max_zoom < min_zoom) { + g_logger(G_LOG_LEVEL_CRITICAL, "Specified min zoom (%i) is larger than max zoom (%i).", min_zoom, max_zoom); return 1; } - if (minZoom < excess_zoomlevels) { - minZoom = excess_zoomlevels; + if (config_file_name_passed) { + int map_section_num = -1; + process_config_file(config_file_name, 0, G_LOG_LEVEL_DEBUG); + + for (int i = 0; i < XMLCONFIGS_MAX; ++i) { + if (maps[i].xmlname && strcmp(maps[i].xmlname, mapname) == 0) { + map_section_num = i; + } + } + + if (map_section_num < 0) { + g_logger(G_LOG_LEVEL_CRITICAL, "Map section '%s' does not exist in config file '%s'.", mapname, config_file_name); + return 1; + } + + if (!max_zoom_passed) { + max_zoom = maps[map_section_num].max_zoom; + max_zoom_passed = 1; + } + + if (!min_zoom_passed) { + min_zoom = maps[map_section_num].min_zoom; + min_zoom_passed = 1; + } + + if (!num_threads_passed) { + num_threads = maps[map_section_num].num_threads; + num_threads_passed = 1; + } + + if (!socketname_passed) { + socketname = strndup(config.socketname, PATH_MAX); + socketname_passed = 1; + } + + if (!tile_dir_passed) { + tile_dir = strndup(maps[map_section_num].tile_dir, PATH_MAX); + tile_dir_passed = 1; + } + } + + store = init_storage_backend(tile_dir); + + if (store == NULL) { + g_logger(G_LOG_LEVEL_CRITICAL, "Failed to initialise storage backend %s", tile_dir); + return 1; + } + + if (min_zoom < excess_zoomlevels) { + min_zoom = excess_zoomlevels; } // initialise arrays for tile markings - tile_requested = (unsigned int **) malloc((maxZoom - excess_zoomlevels + 1) * sizeof(unsigned int *)); + tile_requested = (unsigned int **)malloc((max_zoom - excess_zoomlevels + 1) * sizeof(unsigned int *)); - for (i = 0; i <= maxZoom - excess_zoomlevels; i++) { + for (int i = 0; i <= max_zoom - excess_zoomlevels; i++) { // initialize twopow array twopow[i] = (i == 0) ? 1 : twopow[i - 1] * 2; unsigned long long fourpow = twopow[i] * twopow[i]; - tile_requested[i] = (unsigned int *) calloc((fourpow / METATILE) + 1, 1); + tile_requested[i] = (unsigned int *)calloc((fourpow / METATILE) + 1, 1); if (NULL == tile_requested[i]) { - fprintf(stderr, "not enough memory available.\n"); + g_logger(G_LOG_LEVEL_CRITICAL, "not enough memory available"); return 1; } } - - fprintf(stderr, "Rendering client\n"); - - gettimeofday(&start, NULL); - - if ((touchFrom != -1 && minZoom < touchFrom) - || (deleteFrom != -1 && minZoom < deleteFrom) - || (touchFrom == -1 && deleteFrom == -1)) { + if ((touchFrom != -1 && min_zoom < touchFrom) || (deleteFrom != -1 && min_zoom < deleteFrom) || (touchFrom == -1 && deleteFrom == -1)) { // No need to spawn render threads, when we're not actually going to rerender tiles - spawn_workers(numThreads, spath, maxLoad); + spawn_workers(num_threads, socketname, max_load); doRender = 1; } - store = init_storage_backend(tile_dir); + g_logger(G_LOG_LEVEL_INFO, "Started render_expired with the following options:"); - if (store == NULL) { - fprintf(stderr, "failed to initialise storage backend %s\n", tile_dir); - return 1; + if (config_file_name_passed) { + g_logger(G_LOG_LEVEL_INFO, "\t--config = '%s' (user-specified)", config_file_name); } + g_logger(G_LOG_LEVEL_INFO, "\t--map = '%s' (%s)", mapname, mapname_passed ? "user-specified" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--max-load = '%i' (%s)", max_load, max_load_passed ? "user-specified/from config" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--max-zoom = '%i' (%s)", max_zoom, max_zoom_passed ? "user-specified/from config" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--min-zoom = '%i' (%s)", min_zoom, min_zoom_passed ? "user-specified/from config" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--num-threads = '%i' (%s)", num_threads, num_threads_passed ? "user-specified/from config" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--socket = '%s' (%s)", socketname, socketname_passed ? "user-specified/from config" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--tile-dir = '%s' (%s)", tile_dir, tile_dir_passed ? "user-specified/from config" : "default"); + + gettimeofday(&start, NULL); + while (!feof(stdin)) { struct stat_info s; int n = fscanf(stdin, "%d/%d/%d", &z, &x, &y); - if (verbose) { - printf("read: x=%d y=%d z=%d\n", x, y, z); - } - if (n != 3) { // Discard input line char tmp[1024]; @@ -320,32 +359,41 @@ int main(int argc, char **argv) continue; } - fprintf(stderr, "bad line %d: %s", num_all, tmp); + if (verbose) { + g_logger(G_LOG_LEVEL_WARNING, "bad line %d: %s", num_all, tmp); + } + continue; } - while (z > maxZoom) { + if (verbose) { + g_logger(G_LOG_LEVEL_MESSAGE, "read: x=%d y=%d z=%d", x, y, z); + } + + while (z > max_zoom) { x >>= 1; y >>= 1; z--; } - while (z < maxZoom) { + while (z < max_zoom) { x <<= 1; y <<= 1; z++; } - //printf("loop: x=%d y=%d z=%d up to z=%d\n", x, y, z, minZoom); + g_logger(G_LOG_LEVEL_DEBUG, "loop: x=%d y=%d z=%d up to z=%d", x, y, z, min_zoom); num_read++; if (progress && (num_read % 100) == 0) { - printf("Read and expanded %i tiles from list.\n", num_read); + g_logger(G_LOG_LEVEL_INFO, "Read and expanded %i tiles from list.", num_read); } - for (; z >= minZoom; z--, x >>= 1, y >>= 1) { + for (; z >= min_zoom; z--, x >>= 1, y >>= 1) { + char name[PATH_MAX]; + if (verbose) { - printf("process: x=%d y=%d z=%d\n", x, y, z); + g_logger(G_LOG_LEVEL_MESSAGE, "process: x=%d y=%d z=%d", x, y, z); } // don't do anything if this tile was already requested. @@ -354,7 +402,7 @@ int main(int argc, char **argv) // cause extra work. if (TILE_REQUESTED(z - excess_zoomlevels, x >> excess_zoomlevels, y >> excess_zoomlevels)) { if (verbose) { - printf("already requested\n"); + g_logger(G_LOG_LEVEL_MESSAGE, "already requested"); } break; @@ -367,7 +415,7 @@ int main(int argc, char **argv) // commented out - seems to cause problems in MT environment, // trying to write to already-closed file - //check_load(); + // check_load(); num_all++; s = store->tile_stat(store, mapname, "", x, y, z); @@ -375,42 +423,21 @@ int main(int argc, char **argv) if (s.size > 0) { // Tile exists // tile exists on disk; render it if (deleteFrom != -1 && z >= deleteFrom) { - if (verbose) { - printf("deleting: %s\n", store->tile_storage_id(store, mapname, "", x, y, z, name)); - } - + g_logger(G_LOG_LEVEL_MESSAGE, "delete: %s", store->tile_storage_id(store, mapname, "", x, y, z, name)); store->metatile_delete(store, mapname, x, y, z); num_unlink++; } else if (touchFrom != -1 && z >= touchFrom) { - if (verbose) { - printf("touch: %s\n", store->tile_storage_id(store, mapname, "", x, y, z, name)); - } - + g_logger(G_LOG_LEVEL_MESSAGE, "touch: %s", store->tile_storage_id(store, mapname, "", x, y, z, name)); store->metatile_expire(store, mapname, x, y, z); num_touch++; } else if (doRender) { - printf("render: %s\n", store->tile_storage_id(store, mapname, "", x, y, z, name)); + g_logger(G_LOG_LEVEL_MESSAGE, "render: %s", store->tile_storage_id(store, mapname, "", x, y, z, name)); enqueue(mapname, x, y, z); num_render++; } - - /* - if (!(num_render % 10)) - { - gettimeofday(&end, NULL); - printf("\n"); - printf("Meta tiles rendered: "); - display_rate(start, end, num_render); - printf("Total tiles rendered: "); - display_rate(start, end, num_render * METATILE * METATILE); - printf("Total tiles in input: %d\n", num_read); - printf("Total tiles expanded from input: %d\n", num_all); - printf("Total tiles ignored (not on disk): %d\n", num_ignore); - } - */ } else { if (verbose) { - printf("not on disk: %s\n", store->tile_storage_id(store, mapname, "", x, y, z, name)); + g_logger(G_LOG_LEVEL_MESSAGE, "not on disk: %s", store->tile_storage_id(store, mapname, "", x, y, z, name)); } num_ignore++; @@ -422,36 +449,43 @@ int main(int argc, char **argv) finish_workers(); } - free(spath); + if (config_file_name_passed) { + free((void *)config_file_name); + } - if (mapname != mapname_default) { + if (mapname_passed) { free((void *)mapname); } - if (tile_dir != tile_dir_default) { + if (socketname_passed) { + free((void *)socketname); + } + + if (tile_dir_passed) { free((void *)tile_dir); } store->close_storage(store); free(store); - for (i = 0; i <= maxZoom - excess_zoomlevels; i++) { + for (int i = 0; i <= max_zoom - excess_zoomlevels; i++) { free(tile_requested[i]); } free(tile_requested); gettimeofday(&end, NULL); - printf("\nTotal for all tiles rendered\n"); - printf("Meta tiles rendered: "); + g_logger(G_LOG_LEVEL_MESSAGE, "Read and expanded %i tiles from list.", num_read); + g_logger(G_LOG_LEVEL_MESSAGE, "Total for all tiles rendered"); + g_logger(G_LOG_LEVEL_MESSAGE, "Meta tiles rendered:"); display_rate(start, end, num_render); - printf("Total tiles rendered: "); + g_logger(G_LOG_LEVEL_MESSAGE, "Total tiles rendered:"); display_rate(start, end, num_render * METATILE * METATILE); - printf("Total tiles in input: %d\n", num_read); - printf("Total tiles expanded from input: %d\n", num_all); - printf("Total meta tiles deleted: %d\n", num_unlink); - printf("Total meta tiles touched: %d\n", num_touch); - printf("Total tiles ignored (not on disk): %d\n", num_ignore); + g_logger(G_LOG_LEVEL_MESSAGE, "Total tiles in input: %d", num_read); + g_logger(G_LOG_LEVEL_MESSAGE, "Total tiles expanded from input: %d", num_all); + g_logger(G_LOG_LEVEL_MESSAGE, "Total meta tiles deleted: %d", num_unlink); + g_logger(G_LOG_LEVEL_MESSAGE, "Total meta tiles touched: %d", num_touch); + g_logger(G_LOG_LEVEL_MESSAGE, "Total tiles ignored (not on disk): %d", num_ignore); return 0; } diff --git a/src/render_list.c b/src/render_list.c index 228dfebe..5dcc60aa 100644 --- a/src/render_list.c +++ b/src/render_list.c @@ -15,35 +15,23 @@ * along with this program; If not, see http://www.gnu.org/licenses/. */ +#include +#include +#include #include #include -#include -#include -#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include +#include +#include "config.h" #include "g_logger.h" -#include "gen_tile.h" #include "protocol.h" -#include "config.h" #include "render_config.h" -#include "store.h" -#include "sys_utils.h" #include "render_submit_queue.h" - -const char * tile_dir_default = RENDERD_TILE_DIR; +#include "renderd_config.h" +#include "store.h" #ifndef METATILE #warning("render_list not implemented for non-metatile mode. Feel free to submit fix") @@ -54,67 +42,67 @@ int main(int argc, char **argv) } #else -static int minZoom = 0; -static int maxZoom = MAX_ZOOM; -static int verbose = 0; -static int maxLoad = MAX_LOAD_OLD; - - void display_rate(struct timeval start, struct timeval end, int num) { int d_s, d_us; float sec; - d_s = end.tv_sec - start.tv_sec; + d_s = end.tv_sec - start.tv_sec; d_us = end.tv_usec - start.tv_usec; sec = d_s + d_us / 1000000.0; - printf("Rendered %d tiles in %.2f seconds (%.2f tiles/s)\n", num, sec, num / sec); - fflush(NULL); -} - -int min_max_opt(char *opt_arg, char *opt_type_name, int minimum, int maximum) -{ - int opt = atoi(opt_arg); - float opt_float; - - if (minimum != -1 && opt < minimum) { - fprintf(stderr, "Invalid %s, must be >= %i (%s was provided)\n", opt_type_name, minimum, opt_arg); - exit(1); - } - - if (maximum != -1 && opt > maximum) { - fprintf(stderr, "Invalid %s, must be <= %i (%s was provided)\n", opt_type_name, maximum, opt_arg); - exit(1); - } - - if (sscanf(opt_arg, "%f", &opt_float) != 0) { - if ((float) opt != opt_float) { - fprintf(stderr, "Invalid %s, must be an integer (%s was provided)\n", opt_type_name, opt_arg); - exit(1); - } - } - - return opt; + g_logger(G_LOG_LEVEL_MESSAGE, "\tRendered %d tiles in %.2f seconds (%.2f tiles/s)", num, sec, num / sec); } int main(int argc, char **argv) { - char *spath = strdup(RENDERD_SOCKET); + const char *config_file_name_default = RENDERD_CONFIG; const char *mapname_default = XMLCONFIG_DEFAULT; + const char *socketname_default = RENDERD_SOCKET; + const char *tile_dir_default = RENDERD_TILE_DIR; + int max_load_default = MAX_LOAD_OLD; + int max_x_default = -1; + int max_y_default = -1; + int max_zoom_default = 18; + int min_x_default = -1; + int min_y_default = -1; + int min_zoom_default = 0; + int num_threads_default = 1; + + const char *config_file_name = config_file_name_default; const char *mapname = mapname_default; + const char *socketname = socketname_default; const char *tile_dir = tile_dir_default; - int minX = -1, maxX = -1, minY = -1, maxY = -1; + int max_load = max_load_default; + int max_x = max_x_default; + int max_y = max_y_default; + int max_zoom = max_zoom_default; + int min_x = min_x_default; + int min_y = min_y_default; + int min_zoom = min_zoom_default; + int num_threads = num_threads_default; + + int config_file_name_passed = 0; + int mapname_passed = 0; + int socketname_passed = 0; + int tile_dir_passed = 0; + int max_load_passed = 0; + int max_x_passed = 0; + int max_y_passed = 0; + int max_zoom_passed = 0; + int min_x_passed = 0; + int min_y_passed = 0; + int min_zoom_passed = 0; + int num_threads_passed = 0; + int x, y, z; - char name[PATH_MAX]; struct timeval start, end; int num_render = 0, num_all = 0; - int c; int all = 0; - int numThreads = 1; int force = 0; - struct storage_backend * store; + int verbose = 0; + struct storage_backend *store; struct stat_info s; foreground = 1; @@ -123,6 +111,7 @@ int main(int argc, char **argv) int option_index = 0; static struct option long_options[] = { {"all", no_argument, 0, 'a'}, + {"config", required_argument, 0, 'c'}, {"force", no_argument, 0, 'f'}, {"map", required_argument, 0, 'm'}, {"max-load", required_argument, 0, 'l'}, @@ -142,81 +131,105 @@ int main(int argc, char **argv) {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "afm:l:X:Y:Z:x:y:z:n:s:t:vhV", long_options, &option_index); + int c = getopt_long(argc, argv, "ac:fm:l:X:Y:Z:x:y:z:n:s:t:vhV", long_options, &option_index); if (c == -1) { break; } switch (c) { - case 'a': /* -a, --all */ + case 'a': /* -a, --all */ all = 1; break; - case 's': /* -s, --socket */ - free(spath); - spath = strdup(optarg); + case 'c': /* -c, --config */ + config_file_name = strndup(optarg, PATH_MAX); + config_file_name_passed = 1; + + struct stat buffer; + + if (stat(config_file_name, &buffer) != 0) { + g_logger(G_LOG_LEVEL_CRITICAL, "Config file '%s' does not exist, please specify a valid file", config_file_name); + return 1; + } + break; - case 't': /* -t, --tile-dir */ - tile_dir = strdup(optarg); + case 'f': /* -f, --force */ + force = 1; break; - case 'm': /* -m, --map */ - mapname = strdup(optarg); + case 'm': /* -m, --map */ + mapname = strndup(optarg, XMLCONFIG_MAX); + mapname_passed = 1; break; - case 'l': /* -l, --max-load */ - maxLoad = min_max_opt(optarg, "maximum load", 0, -1); + case 'l': /* -l, --max-load */ + max_load = min_max_int_opt(optarg, "maximum load", 0, -1); + max_load_passed = 1; break; - case 'n': /* -n, --num-threads */ - numThreads = min_max_opt(optarg, "number of threads", 1, -1); + case 'X': /* -X, --max-x */ + max_x = min_max_int_opt(optarg, "maximum X tile coordinate", 0, -1); + max_x_passed = 1; break; - case 'x': /* -x, --min-x */ - minX = min_max_opt(optarg, "minimum X tile coordinate", 0, -1); + case 'Y': /* -Y, --max-y */ + max_y = min_max_int_opt(optarg, "maximum Y tile coordinate", 0, -1); + max_y_passed = 1; break; - case 'X': /* -X, --max-x */ - maxX = min_max_opt(optarg, "maximum X tile coordinate", 0, -1); + case 'Z': /* -Z, --max-zoom */ + max_zoom = min_max_int_opt(optarg, "maximum zoom", 0, MAX_ZOOM); + max_zoom_passed = 1; break; - case 'y': /* -y, --min-y */ - minY = min_max_opt(optarg, "minimum Y tile coordinate", 0, -1); + case 'x': /* -x, --min-x */ + min_x = min_max_int_opt(optarg, "minimum X tile coordinate", 0, -1); + min_x_passed = 1; break; - case 'Y': /* -Y, --max-y */ - maxY = min_max_opt(optarg, "maximum Y tile coordinate", 0, -1); + case 'y': /* -y, --min-y */ + min_y = min_max_int_opt(optarg, "minimum Y tile coordinate", 0, -1); + min_y_passed = 1; break; - case 'z': /* -z, --min-zoom */ - minZoom = min_max_opt(optarg, "minimum zoom", 0, MAX_ZOOM); + case 'z': /* -z, --min-zoom */ + min_zoom = min_max_int_opt(optarg, "minimum zoom", 0, MAX_ZOOM); + min_zoom_passed = 1; break; - case 'Z': /* -Z, --max-zoom */ - maxZoom = min_max_opt(optarg, "maximum zoom", 0, MAX_ZOOM); + case 'n': /* -n, --num-threads */ + num_threads = min_max_int_opt(optarg, "number of threads", 1, -1); + num_threads_passed = 1; break; - case 'f': /* -f, --force */ - force = 1; + case 's': /* -s, --socket */ + socketname = strndup(optarg, PATH_MAX); + socketname_passed = 1; break; - case 'v': /* -v, --verbose */ + case 't': /* -t, --tile-dir */ + tile_dir = strndup(optarg, PATH_MAX); + tile_dir_passed = 1; + break; + + case 'v': /* -v, --verbose */ verbose = 1; break; - case 'h': /* -h, --help */ + case 'h': /* -h, --help */ fprintf(stderr, "Usage: render_list [OPTION] ...\n"); fprintf(stderr, " -a, --all render all tiles in given zoom level range instead of reading from STDIN\n"); + fprintf(stderr, " -c, --config=CONFIG specify the renderd config file (default is off)\n"); fprintf(stderr, " -f, --force render tiles even if they seem current\n"); - fprintf(stderr, " -l, --max-load=LOAD sleep if load is this high (defaults to %d)\n", MAX_LOAD_OLD); - fprintf(stderr, " -m, --map=MAP render tiles in this map (defaults to '" XMLCONFIG_DEFAULT "')\n"); - fprintf(stderr, " -n, --num-threads=N the number of parallel request threads (default 1)\n"); - fprintf(stderr, " -s, --socket=SOCKET|HOSTNAME:PORT unix domain socket name or hostname and port for contacting renderd\n"); - fprintf(stderr, " -t, --tile-dir tile cache directory (defaults to '" RENDERD_TILE_DIR "')\n"); - fprintf(stderr, " -Z, --max-zoom=ZOOM filter input to only render tiles less than or equal to this zoom level (default is %d)\n", MAX_ZOOM); - fprintf(stderr, " -z, --min-zoom=ZOOM filter input to only render tiles greater or equal to this zoom level (default is 0)\n"); + fprintf(stderr, " -l, --max-load=LOAD sleep if load is this high (default is '%d')\n", max_load_default); + fprintf(stderr, " -m, --map=MAP render tiles in this map (default is '%s')\n", mapname_default); + fprintf(stderr, " -l, --max-load=LOAD sleep if load is this high (default is '%d')\n", max_load_default); + fprintf(stderr, " -s, --socket=SOCKET|HOSTNAME:PORT unix domain socket name or hostname and port for contacting renderd (default is '%s')\n", socketname_default); + fprintf(stderr, " -t, --tile-dir=TILE_DIR tile cache directory (default is '%s')\n", tile_dir_default); + fprintf(stderr, " -Z, --max-zoom=ZOOM filter input to only render tiles less than or equal to this zoom level (default is '%d')\n", max_zoom_default); + fprintf(stderr, " -z, --min-zoom=ZOOM filter input to only render tiles greater than or equal to this zoom level (default is '%d')\n", min_zoom_default); fprintf(stderr, "\n"); fprintf(stderr, "If you are using --all, you can restrict the tile range by adding these options:\n"); fprintf(stderr, " (please note that tile coordinates must be positive integers and are not latitude and longitude values)\n"); @@ -236,85 +249,137 @@ int main(int argc, char **argv) fprintf(stderr, " 1 0 1\n"); fprintf(stderr, " 1 1 1\n"); fprintf(stderr, "The above would cause all 4 tiles at zoom 1 to be rendered\n"); - exit(0); + return 0; - case 'V': + case 'V': /* -V, --version */ fprintf(stdout, "%s\n", VERSION); - exit(0); + return 0; default: - fprintf(stderr, "unhandled char '%c'\n", c); - exit(1); + g_logger(G_LOG_LEVEL_CRITICAL, "unhandled char '%c'", c); + return 1; } } - if (maxZoom < minZoom) { - fprintf(stderr, "Invalid zoom range, max zoom must be greater or equal to minimum zoom\n"); + if (max_zoom < min_zoom) { + g_logger(G_LOG_LEVEL_CRITICAL, "Specified min zoom (%i) is larger than max zoom (%i).", min_zoom, max_zoom); return 1; } + if (config_file_name_passed) { + int map_section_num = -1; + process_config_file(config_file_name, 0, G_LOG_LEVEL_DEBUG); + + for (int i = 0; i < XMLCONFIGS_MAX; ++i) { + if (maps[i].xmlname && strcmp(maps[i].xmlname, mapname) == 0) { + map_section_num = i; + } + } + + if (map_section_num < 0) { + g_logger(G_LOG_LEVEL_CRITICAL, "Map section '%s' does not exist in config file '%s'.", mapname, config_file_name); + return 1; + } + + if (!max_zoom_passed) { + max_zoom = maps[map_section_num].max_zoom; + max_zoom_passed = 1; + } + + if (!min_zoom_passed) { + min_zoom = maps[map_section_num].min_zoom; + min_zoom_passed = 1; + } + + if (!num_threads_passed) { + num_threads = maps[map_section_num].num_threads; + num_threads_passed = 1; + } + + if (!socketname_passed) { + socketname = strndup(config.socketname, PATH_MAX); + socketname_passed = 1; + } + + if (!tile_dir_passed) { + tile_dir = strndup(maps[map_section_num].tile_dir, PATH_MAX); + tile_dir_passed = 1; + } + } + store = init_storage_backend(tile_dir); if (store == NULL) { - fprintf(stderr, "Failed to initialise storage backend %s\n", tile_dir); + g_logger(G_LOG_LEVEL_CRITICAL, "Failed to initialise storage backend %s", tile_dir); return 1; } if (all) { - if ((minX != -1 || minY != -1 || maxX != -1 || maxY != -1) && minZoom != maxZoom) { - fprintf(stderr, "min-zoom must be equal to max-zoom when using min-x, max-x, min-y, or max-y options\n"); + if ((min_x != -1 || min_y != -1 || max_x != -1 || max_y != -1) && min_zoom != max_zoom) { + g_logger(G_LOG_LEVEL_CRITICAL, "min-zoom must be equal to max-zoom when using min-x, max-x, min-y, or max-y options"); return 1; } - if (minX == -1) { - minX = 0; + if (min_x == -1) { + min_x = 0; } - if (minY == -1) { - minY = 0; + if (min_y == -1) { + min_y = 0; } - int lz = (1 << minZoom) - 1; + int lz = (1 << min_zoom) - 1; - if (minZoom == maxZoom) { - if (maxX == -1) { - maxX = lz; + if (min_zoom == max_zoom) { + if (max_x == -1) { + max_x = lz; } - if (maxY == -1) { - maxY = lz; + if (max_y == -1) { + max_y = lz; } - if (minX > lz || minY > lz || maxX > lz || maxY > lz) { - fprintf(stderr, "Invalid range, x and y values must be <= %d (2^zoom-1)\n", lz); + if (min_x > lz || min_y > lz || max_x > lz || max_y > lz) { + g_logger(G_LOG_LEVEL_CRITICAL, "Invalid range, x and y values must be <= %d (2^zoom-1)", lz); return 1; } } - if (minX < 0 || minY < 0 || maxX < -1 || maxY < -1) { - fprintf(stderr, "Invalid range, x and y values must be >= 0\n"); + if (min_x < 0 || min_y < 0 || max_x < -1 || max_y < -1) { + g_logger(G_LOG_LEVEL_CRITICAL, "Invalid range, x and y values must be >= 0"); return 1; } + } + + g_logger(G_LOG_LEVEL_INFO, "Started render_list with the following options:"); + if (config_file_name_passed) { + g_logger(G_LOG_LEVEL_INFO, "\t--config = '%s' (user-specified)", config_file_name); } - fprintf(stderr, "Rendering client\n"); + g_logger(G_LOG_LEVEL_INFO, "\t--map = '%s' (%s)", mapname, mapname_passed ? "user-specified" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--max-load = '%i' (%s)", max_load, max_load_passed ? "user-specified/from config" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--max-zoom = '%i' (%s)", max_zoom, max_zoom_passed ? "user-specified/from config" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--min-zoom = '%i' (%s)", min_zoom, min_zoom_passed ? "user-specified/from config" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--num-threads = '%i' (%s)", num_threads, num_threads_passed ? "user-specified/from config" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--socket = '%s' (%s)", socketname, socketname_passed ? "user-specified/from config" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--tile-dir = '%s' (%s)", tile_dir, tile_dir_passed ? "user-specified/from config" : "default"); gettimeofday(&start, NULL); - spawn_workers(numThreads, spath, maxLoad); + spawn_workers(num_threads, socketname, max_load); if (all) { int x, y, z; - printf("Rendering all tiles from zoom %d to zoom %d\n", minZoom, maxZoom); + g_logger(G_LOG_LEVEL_MESSAGE, "Rendering all tiles from zoom %d to zoom %d", min_zoom, max_zoom); - for (z = minZoom; z <= maxZoom; z++) { - int current_maxX = (maxX == -1) ? (1 << z) - 1 : maxX; - int current_maxY = (maxY == -1) ? (1 << z) - 1 : maxY; - printf("Rendering all tiles for zoom %d from (%d, %d) to (%d, %d)\n", z, minX, minY, current_maxX, current_maxY); + for (z = min_zoom; z <= max_zoom; z++) { + int current_max_x = (max_x == -1) ? (1 << z) - 1 : max_x; + int current_max_y = (max_y == -1) ? (1 << z) - 1 : max_y; + g_logger(G_LOG_LEVEL_MESSAGE, "Rendering all tiles for zoom %d from (%d, %d) to (%d, %d)", z, min_x, min_y, current_max_x, current_max_y); - for (x = minX; x <= current_maxX; x += METATILE) { - for (y = minY; y <= current_maxY; y += METATILE) { + for (x = min_x; x <= current_max_x; x += METATILE) { + for (y = min_y; y <= current_max_y; y += METATILE) { if (!force) { s = store->tile_stat(store, mapname, "", x, y, z); } @@ -325,7 +390,6 @@ int main(int argc, char **argv) } num_all++; - } } } @@ -333,28 +397,28 @@ int main(int argc, char **argv) while (!feof(stdin)) { int n = fscanf(stdin, "%d %d %d", &x, &y, &z); - if (verbose) - - - if (n != 3) { - // Discard input line - char tmp[1024]; - char *r = fgets(tmp, sizeof(tmp), stdin); - - if (!r) { - continue; - } + if (n != 3) { + // Discard input line + char tmp[1024]; + char *r = fgets(tmp, sizeof(tmp), stdin); - fprintf(stderr, "bad line %d: %s", num_all, tmp); + if (!r) { continue; } + if (verbose) { + g_logger(G_LOG_LEVEL_WARNING, "bad line %d: %s", num_all, tmp); + } + + continue; + } + if (verbose) { - printf("got: x(%d) y(%d) z(%d)\n", x, y, z); + g_logger(G_LOG_LEVEL_MESSAGE, "got: x(%d) y(%d) z(%d)", x, y, z); } - if (z < minZoom || z > maxZoom) { - printf("Ignoring tile, zoom %d outside valid range (%d..%d)\n", z, minZoom, maxZoom); + if (z < min_zoom || z > max_zoom) { + g_logger(G_LOG_LEVEL_MESSAGE, "Ignoring tile, zoom %d outside valid range (%d..%d)", z, min_zoom, max_zoom); continue; } @@ -372,46 +436,50 @@ int main(int argc, char **argv) // Attempts to adjust the stats for the QMAX tiles which are likely in the queue if (!(num_render % 10)) { gettimeofday(&end, NULL); - printf("\n"); - printf("Meta tiles rendered: "); + g_logger(G_LOG_LEVEL_MESSAGE, "Meta tiles rendered:"); display_rate(start, end, num_render); - printf("Total tiles rendered: "); - display_rate(start, end, (num_render) * METATILE * METATILE); - printf("Total tiles handled from input: "); + g_logger(G_LOG_LEVEL_MESSAGE, "Total tiles rendered:"); + display_rate(start, end, num_render * METATILE * METATILE); + g_logger(G_LOG_LEVEL_MESSAGE, "Total tiles handled:"); display_rate(start, end, num_all); } } else { if (verbose) { - printf("Tile %s is clean, ignoring\n", store->tile_storage_id(store, mapname, "", x, y, z, name)); + char name[PATH_MAX]; + g_logger(G_LOG_LEVEL_MESSAGE, "Tile %s is clean, ignoring", store->tile_storage_id(store, mapname, "", x, y, z, name)); } } } } - store->close_storage(store); - free(store); finish_workers(); - free(spath); + if (config_file_name_passed) { + free((void *)config_file_name); + } - if (mapname != mapname_default) { + if (mapname_passed) { free((void *)mapname); } - if (tile_dir != tile_dir_default) { + if (socketname_passed) { + free((void *)socketname); + } + + if (tile_dir_passed) { free((void *)tile_dir); } + store->close_storage(store); + free(store); gettimeofday(&end, NULL); - printf("\n*****************************************************\n"); - printf("*****************************************************\n"); - printf("Total for all tiles rendered\n"); - printf("Meta tiles rendered: "); + g_logger(G_LOG_LEVEL_MESSAGE, "Total for all tiles rendered"); + g_logger(G_LOG_LEVEL_MESSAGE, "Meta tiles rendered:"); display_rate(start, end, num_render); - printf("Total tiles rendered: "); + g_logger(G_LOG_LEVEL_MESSAGE, "Total tiles rendered:"); display_rate(start, end, num_render * METATILE * METATILE); - printf("Total tiles handled: "); + g_logger(G_LOG_LEVEL_MESSAGE, "Total tiles handled:"); display_rate(start, end, num_all); print_statistics(); diff --git a/src/render_old.c b/src/render_old.c index 9ded594a..9bb8e805 100644 --- a/src/render_old.c +++ b/src/render_old.c @@ -15,37 +15,27 @@ * along with this program; If not, see http://www.gnu.org/licenses/. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include #include -#include -#include -#include +#include #include +#include #include +#include +#include +#include +#include -#include - +#include "config.h" #include "g_logger.h" -#include "gen_tile.h" #include "protocol.h" -#include "config.h" #include "render_config.h" -#include "store_file_utils.h" #include "render_submit_queue.h" +#include "renderd_config.h" +#include "store_file_utils.h" #include "sys_utils.h" -const char * tile_dir_default = RENDERD_TILE_DIR; - #ifndef METATILE #warning("render_old not implemented for non-metatile mode. Feel free to submit fix") int main(int argc, char **argv) @@ -55,35 +45,28 @@ int main(int argc, char **argv) } #else -#define INILINE_MAX 256 -static int minZoom = 0; -static int maxZoom = MAX_ZOOM; -static int verbose = 0; static int num_render = 0, num_all = 0; -static int max_load = MAX_LOAD_OLD; -static time_t planetTime; +static int max_load; +static time_t planet_timestamp = 0; static struct timeval start, end; - - void display_rate(struct timeval start, struct timeval end, int num) { int d_s, d_us; float sec; - d_s = end.tv_sec - start.tv_sec; + d_s = end.tv_sec - start.tv_sec; d_us = end.tv_usec - start.tv_usec; sec = d_s + d_us / 1000000.0; - printf("%d tiles in %.2f seconds (%.2f tiles/s)\n", num, sec, num / sec); - fflush(NULL); + g_logger(G_LOG_LEVEL_MESSAGE, "\tRendered %d tiles in %.2f seconds (%.2f tiles/s)", num, sec, num / sec); } -static time_t getPlanetTime(const char *tile_dir) +static time_t get_planet_time(const char *tile_dir) { static time_t last_check; - static time_t planet_timestamp; + static time_t planet_time; time_t now = time(NULL); struct stat buf; char filename[PATH_MAX]; @@ -92,23 +75,23 @@ static time_t getPlanetTime(const char *tile_dir) // Only check for updates periodically if (now < last_check + 300) { - return planet_timestamp; + return planet_time; } last_check = now; if (stat(filename, &buf)) { - fprintf(stderr, "Planet timestamp file (%s) is missing\n", filename); + g_logger(G_LOG_LEVEL_MESSAGE, "Planet timestamp file (%s) is missing", filename); // Make something up - planet_timestamp = now - 3 * 24 * 60 * 60; + planet_time = now - 3 * 24 * 60 * 60; } else { - if (buf.st_mtime != planet_timestamp) { - printf("Planet file updated at %s", ctime(&buf.st_mtime)); - planet_timestamp = buf.st_mtime; + if (buf.st_mtime != planet_time) { + g_logger(G_LOG_LEVEL_MESSAGE, "Planet file updated at %s", strtok(ctime(&buf.st_mtime), "\n")); + planet_time = buf.st_mtime; } } - return planet_timestamp; + return planet_time; } static void check_load(void) @@ -116,7 +99,7 @@ static void check_load(void) double avg = get_load_avg(); while (avg >= max_load) { - printf("Load average %f, sleeping\n", avg); + g_logger(G_LOG_LEVEL_MESSAGE, "Load average %f, sleeping", avg); sleep(5); avg = get_load_avg(); } @@ -131,7 +114,7 @@ static void descend(const char *tile_dir, const char *search) int x, y, z; if (!tiles) { - fprintf(stderr, "Unable to open directory: %s\n", search); + g_logger(G_LOG_LEVEL_DEBUG, "%s: %s", strerror(errno), search); return; } @@ -159,43 +142,65 @@ static void descend(const char *tile_dir, const char *search) p = strrchr(path, '.'); if (p && !strcmp(p, ".meta")) { - num_all++; - - if (planetTime > b.st_mtime) { + if (planet_timestamp > b.st_mtime) { // request rendering of old tile path_to_xyz(tile_dir, path, mapname, &x, &y, &z); enqueue(mapname, x, y, z); + num_render++; } + + num_all++; } } closedir(tiles); } -void render_layer(const char *tilepath, const char *name) +void render_layer(const char *tile_dir, const char *mapname, int min_zoom, int max_zoom, int verbose) { - int z; - - for (z = minZoom; z <= maxZoom; z++) { + for (int z = min_zoom; z <= max_zoom; z++) { if (verbose) { - printf("Rendering zoom %d\n", z); + g_logger(G_LOG_LEVEL_MESSAGE, "Rendering zoom %d", z); } - char path[PATH_MAX]; - snprintf(path, PATH_MAX, "%s/%s/%d", tilepath, name, z); - descend(tilepath, path); + char search[PATH_MAX]; + snprintf(search, PATH_MAX, "%s/%s/%d", tile_dir, mapname, z); + descend(tile_dir, search); } } int main(int argc, char **argv) { - char spath[PATH_MAX] = RENDERD_SOCKET; - char *config_file = RENDERD_CONFIG; + const char *config_file_name_default = RENDERD_CONFIG; + const char *mapname_default = XMLCONFIG_DEFAULT; + const char *socketname_default = RENDERD_SOCKET; + const char *tile_dir_default = RENDERD_TILE_DIR; + int max_load_default = MAX_LOAD_OLD; + int max_zoom_default = 18; + int min_zoom_default = 0; + int num_threads_default = 1; + + const char *config_file_name = config_file_name_default; + const char *mapname = mapname_default; + const char *socketname = socketname_default; const char *tile_dir = tile_dir_default; - char *map = NULL; - int c; - int numThreads = 1; + max_load = max_load_default; + int max_zoom = max_zoom_default; + int min_zoom = min_zoom_default; + int num_threads = num_threads_default; + + int config_file_name_passed = 0; + int mapname_passed = 0; + int socketname_passed = 0; + int tile_dir_passed = 0; + int max_load_passed = 0; + int max_zoom_passed = 0; + int min_zoom_passed = 0; + int num_threads_passed = 0; + + int map_section_num = -1; int dd, mm, yy; + int verbose = 0; struct tm tm; foreground = 1; @@ -219,72 +224,62 @@ int main(int argc, char **argv) {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "c:m:l:Z:z:n:s:t:T:vhV", long_options, &option_index); + int c = getopt_long(argc, argv, "c:m:l:Z:z:n:s:t:T:vhV", long_options, &option_index); if (c == -1) { break; } switch (c) { - case 's': /* -s, --socket */ - strncpy(spath, optarg, PATH_MAX - 1); - spath[PATH_MAX - 1] = 0; - break; + case 'c': /* -c, --config */ + config_file_name = strndup(optarg, PATH_MAX); + config_file_name_passed = 1; - case 't': /* -t, --tile-dir */ - tile_dir = strdup(optarg); - break; - - case 'c': /* -c, --config */ - config_file = strdup(optarg); - break; - - case 'm': /* -m, --map */ - map = strdup(optarg); - break; - - case 'n': /* -n, --num-threads */ - numThreads = atoi(optarg); + struct stat buffer; - if (numThreads <= 0) { - fprintf(stderr, "Invalid number of threads, must be at least 1\n"); + if (stat(config_file_name, &buffer) != 0) { + g_logger(G_LOG_LEVEL_CRITICAL, "Config file '%s' does not exist, please specify a valid file", config_file_name); return 1; } break; - case 'z': /* -z, --min-zoom */ - minZoom = atoi(optarg); - - if (minZoom < 0 || minZoom > MAX_ZOOM) { - fprintf(stderr, "Invalid minimum zoom selected, must be between 0 and %d\n", MAX_ZOOM); - return 1; - } - + case 'm': /* -m, --map */ + mapname = strndup(optarg, XMLCONFIG_MAX); + mapname_passed = 1; break; - case 'Z': /* -Z, --max-zoom */ - maxZoom = atoi(optarg); + case 'l': /* -l, --max-load */ + max_load = min_max_int_opt(optarg, "maximum load", 0, -1); + max_load_passed = 1; + break; - if (maxZoom < 0 || maxZoom > MAX_ZOOM) { - fprintf(stderr, "Invalid maximum zoom selected, must be between 0 and %d\n", MAX_ZOOM); - return 1; - } + case 'Z': /* -Z, --max-zoom */ + max_zoom = min_max_int_opt(optarg, "maximum zoom", 0, MAX_ZOOM); + max_zoom_passed = 1; + break; + case 'z': /* -z, --min-zoom */ + min_zoom = min_max_int_opt(optarg, "minimum zoom", 0, MAX_ZOOM); + min_zoom_passed = 1; break; - case 'l': - max_load = atoi(optarg); + case 'n': /* -n, --num-threads */ + num_threads = min_max_int_opt(optarg, "number of threads", 1, -1); + num_threads_passed = 1; + break; - if (max_load < 0) { - fprintf(stderr, "Invalid maximum load specified, must be greater than 0\n"); - return 1; - } + case 's': /* -s, --socket */ + socketname = strndup(optarg, PATH_MAX); + socketname_passed = 1; + break; + case 't': /* -t, --tile-dir */ + tile_dir = strndup(optarg, PATH_MAX); + tile_dir_passed = 1; break; case 'T': - if (sscanf(optarg, "%d/%d/%d", &dd, &mm, &yy) == 3) { if (yy > 100) { yy -= 1900; @@ -297,114 +292,130 @@ int main(int argc, char **argv) memset(&tm, 0, sizeof(tm)); tm.tm_mday = dd; tm.tm_mon = mm - 1; - tm.tm_year = yy; - planetTime = mktime(&tm); + tm.tm_year = yy; + planet_timestamp = mktime(&tm); } else if (sscanf(optarg, "%d", &dd) == 1) { - planetTime = dd; + planet_timestamp = dd; } else { - fprintf(stderr, "Invalid planet time stamp, must be a unix timestamp or in the format dd/mm/yyyy\n"); + g_logger(G_LOG_LEVEL_CRITICAL, "Invalid planet timestamp, must be a unix timestamp or in the format dd/mm/yyyy"); return 1; } break; - case 'v': /* -v, --verbose */ + case 'v': /* -v, --verbose */ verbose = 1; break; - case 'h': /* -h, --help */ + case 'h': /* -h, --help */ fprintf(stderr, "Usage: render_old [OPTION] ...\n"); fprintf(stderr, "Search the rendered tiles and re-render tiles which are older then the last planet import\n"); - fprintf(stderr, " -c, --config=CONFIG specify the renderd config file\n"); - fprintf(stderr, " -l, --max-load=LOAD maximum system load with which requests are submitted\n"); - fprintf(stderr, " -m, --map=STYLE Instead of going through all styls of CONFIG, only use a specific map-style\n"); - fprintf(stderr, " -n, --num-threads=N the number of parallel request threads (default 1)\n"); - fprintf(stderr, " -s, --socket=SOCKET|HOSTNAME:PORT unix domain socket name or hostname and port for contacting renderd\n"); - fprintf(stderr, " -t, --tile-dir tile cache directory (defaults to '" RENDERD_TILE_DIR "')\n"); + fprintf(stderr, " -c, --config=CONFIG specify the renderd config file (default is '%s')\n", config_file_name_default); + fprintf(stderr, " -l, --max-load=LOAD sleep if load is this high (default is '%d')\n", max_load_default); + fprintf(stderr, " -m, --map=STYLE Instead of going through all styles of CONFIG, only use a specific map-style\n"); + fprintf(stderr, " -n, --num-threads=N the number of parallel request threads (default is '%d')\n", num_threads_default); + fprintf(stderr, " -s, --socket=SOCKET|HOSTNAME:PORT unix domain socket name or hostname and port for contacting renderd (default is '%s')\n", socketname_default); + fprintf(stderr, " -t, --tile-dir=TILE_DIR tile cache directory (default is '%s')\n", tile_dir_default); fprintf(stderr, " -T, --timestamp=DD/MM/YY Overwrite the assumed data of the planet import\n"); - fprintf(stderr, " -Z, --max-zoom=ZOOM filter input to only render tiles less than or equal to this zoom level (default is %d)\n", MAX_ZOOM); - fprintf(stderr, " -z, --min-zoom=ZOOM filter input to only render tiles greater or equal to this zoom level (default is 0)\n"); + fprintf(stderr, " -Z, --max-zoom=ZOOM filter input to only render tiles less than or equal to this zoom level (default is '%d')\n", max_zoom_default); + fprintf(stderr, " -z, --min-zoom=ZOOM filter input to only render tiles greater than or equal to this zoom level (default is '%d')\n", min_zoom_default); fprintf(stderr, "\n"); fprintf(stderr, " -h, --help display this help and exit\n"); fprintf(stderr, " -V, --version display the version number and exit\n"); - exit(0); + return 0; - case 'V': + case 'V': /* -V, --version */ fprintf(stdout, "%s\n", VERSION); - exit(0); + return 0; default: - fprintf(stderr, "unhandled char '%c'\n", c); - exit(1); + g_logger(G_LOG_LEVEL_CRITICAL, "unhandled char '%c'", c); + return 1; } } - if (maxZoom < minZoom) { - fprintf(stderr, "Invalid zoom range, max zoom must be greater or equal to minimum zoom\n"); + if (max_zoom < min_zoom) { + g_logger(G_LOG_LEVEL_CRITICAL, "Specified min zoom (%i) is larger than max zoom (%i).", min_zoom, max_zoom); return 1; } - fprintf(stderr, "Rendering old tiles\n"); + process_config_file(config_file_name, 0, G_LOG_LEVEL_DEBUG); - if (planetTime == 0) { - planetTime = getPlanetTime(tile_dir); - } else { - printf("Overwriting planet file update to %s", ctime(&planetTime)); + for (int i = 0; i < XMLCONFIGS_MAX; ++i) { + if (mapname_passed && maps[i].xmlname && strcmp(maps[i].xmlname, mapname) == 0) { + map_section_num = i; + } } - gettimeofday(&start, NULL); + if (mapname_passed && map_section_num < 0) { + g_logger(G_LOG_LEVEL_CRITICAL, "Map section '%s' does not exist in config file '%s'.", mapname, config_file_name); + return 1; + } + + if (!socketname_passed) { + socketname = strndup(config.socketname, PATH_MAX); + socketname_passed = 1; + } - FILE * hini ; - char line[INILINE_MAX]; - char value[INILINE_MAX]; + g_logger(G_LOG_LEVEL_INFO, "Started render_old with the following options:"); + g_logger(G_LOG_LEVEL_INFO, "\t--config = '%s' (%s)", config_file_name, config_file_name_passed ? "user-specified" : "default"); - // Load the config - if ((hini = fopen(config_file, "r")) == NULL) { - fprintf(stderr, "Config: cannot open %s\n", config_file); - exit(7); + if (mapname_passed) { + g_logger(G_LOG_LEVEL_INFO, "\t--map = '%s' (user-specified)", mapname); } - spawn_workers(numThreads, spath, max_load); + g_logger(G_LOG_LEVEL_INFO, "\t--max-load = '%i' (%s)", max_load, max_load_passed ? "user-specified/from config" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--max-zoom = '%i' (%s)", max_zoom, max_zoom_passed ? "user-specified/from config" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--min-zoom = '%i' (%s)", min_zoom, min_zoom_passed ? "user-specified/from config" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--num-threads = '%i' (%s)", num_threads, num_threads_passed ? "user-specified/from config" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--socket = '%s' (%s)", socketname, socketname_passed ? "user-specified/from config" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--tile-dir = '%s' (%s)", tile_dir, tile_dir_passed ? "user-specified/from config" : "default"); - if (map) { - render_layer(tile_dir, map); + if (planet_timestamp == 0) { + planet_timestamp = get_planet_time(tile_dir); } else { - while (fgets(line, INILINE_MAX, hini) != NULL) { - if (line[0] == '[') { - if (strlen(line) >= XMLCONFIG_MAX) { - fprintf(stderr, "XML name too long: %s\n", line); - exit(7); - } + g_logger(G_LOG_LEVEL_MESSAGE, "Overwriting planet file update to %s", strtok(ctime(&planet_timestamp), "\n")); + } - if (sscanf(line, "[%[^]]", value) != 1) { - fprintf(stderr, "Config: malformed config file on line %s\n", line); - exit(7); - }; + gettimeofday(&start, NULL); - // Skip mapnik & renderd sections which are config, not tile layers - if (strcmp(value, "mapnik") && strncmp(value, "renderd", 7)) { - render_layer(tile_dir, value); - } - } + spawn_workers(num_threads, socketname, max_load); + + for (int i = 0; i < XMLCONFIGS_MAX; ++i) { + if (mapname_passed && maps[i].xmlname && strcmp(maps[i].xmlname, mapname) != 0) { + continue; } - } - fclose(hini); - free(map); + if (maps[i].xmlname != NULL) { + if (!max_zoom_passed) { + max_zoom = maps[i].max_zoom; + } + + if (!min_zoom_passed) { + min_zoom = maps[i].min_zoom; + } + + if (!tile_dir_passed) { + tile_dir = strndup(maps[i].tile_dir, PATH_MAX); + } + + if (verbose) { + g_logger(G_LOG_LEVEL_MESSAGE, "Rendering map '%s' from zoom '%i' to zoom '%i'", maps[i].xmlname, min_zoom, max_zoom); + } - if (tile_dir != tile_dir_default) { - free((void *)tile_dir); + render_layer(tile_dir, maps[i].xmlname, min_zoom, max_zoom, verbose); + } } finish_workers(); gettimeofday(&end, NULL); - printf("\nTotal for all tiles rendered\n"); - printf("Meta tiles rendered: "); + g_logger(G_LOG_LEVEL_MESSAGE, "Total for all tiles rendered"); + g_logger(G_LOG_LEVEL_MESSAGE, "Meta tiles rendered:"); display_rate(start, end, num_render); - printf("Total tiles rendered: "); + g_logger(G_LOG_LEVEL_MESSAGE, "Total tiles rendered:"); display_rate(start, end, num_render * METATILE * METATILE); - printf("Total tiles handled: "); + g_logger(G_LOG_LEVEL_MESSAGE, "Total tiles handled:"); display_rate(start, end, num_all); return 0; diff --git a/src/render_speedtest.cpp b/src/render_speedtest.cpp index 71dfb30e..00b03af9 100644 --- a/src/render_speedtest.cpp +++ b/src/render_speedtest.cpp @@ -15,32 +15,24 @@ * along with this program; If not, see http://www.gnu.org/licenses/. */ +#include +#include +#include +#include #include -#include -#include -#include -#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include -#include "g_logger.h" -#include "gen_tile.h" -#include "protocol.h" #include "config.h" +#include "g_logger.h" #include "render_config.h" #include "render_submit_queue.h" +#include "renderd_config.h" - -#define DEG_TO_RAD (M_PI/180) -#define RAD_TO_DEG (180/M_PI) +#define DEG_TO_RAD (M_PI / 180) +#define RAD_TO_DEG (180 / M_PI) #ifndef METATILE #warning("Speed test not implemented for non-metatile mode. Feel free to submit fix") @@ -72,7 +64,6 @@ static double boundx1 = 3.2; static double boundy1 = 58.8; #endif - static double minmax(double a, double b, double c) { a = MAX(a, b); @@ -124,37 +115,48 @@ void display_rate(struct timeval start, struct timeval end, int num) int d_s, d_us; float sec; - d_s = end.tv_sec - start.tv_sec; + d_s = end.tv_sec - start.tv_sec; d_us = end.tv_usec - start.tv_usec; sec = d_s + d_us / 1000000.0; - printf("Rendered %d tiles in %.2f seconds (%.2f tiles/s)\n", num, sec, num / sec); - fflush(NULL); + g_logger(G_LOG_LEVEL_MESSAGE, "\tRendered %d tiles in %.2f seconds (%.2f tiles/s)", num, sec, num / sec); } int main(int argc, char **argv) { - const char *spath = RENDERD_SOCKET; - int fd; - struct sockaddr_un addr; - int ret = 0; + const char *config_file_name_default = RENDERD_CONFIG; + const char *mapname_default = XMLCONFIG_DEFAULT; + const char *socketname_default = RENDERD_SOCKET; + int max_zoom_default = 18; + int min_zoom_default = 0; + int num_threads_default = 1; + + const char *config_file_name = config_file_name_default; + const char *mapname = mapname_default; + const char *socketname = socketname_default; + int max_zoom = max_zoom_default; + int min_zoom = min_zoom_default; + int num_threads = num_threads_default; + + int config_file_name_passed = 0; + int mapname_passed = 0; + int socketname_passed = 0; + int max_zoom_passed = 0; + int min_zoom_passed = 0; + int num_threads_passed = 0; + int z; - int c; - char name[PATH_MAX]; struct timeval start, end; struct timeval start_all, end_all; - int num, num_all = 0; - const char * mapname = XMLCONFIG_DEFAULT; - int maxZoom = MAX_ZOOM; - int minZoom = 0; - int numThreads = 1; + int num_all = 0; foreground = 1; while (1) { int option_index = 0; static struct option long_options[] = { + {"config", required_argument, 0, 'c'}, {"map", required_argument, 0, 'm'}, {"max-zoom", required_argument, 0, 'Z'}, {"min-zoom", required_argument, 0, 'z'}, @@ -166,83 +168,135 @@ int main(int argc, char **argv) {0, 0, 0, 0} }; - c = getopt_long(argc, argv, "m:Z:z:n:s:hV", long_options, &option_index); + int c = getopt_long(argc, argv, "c:m:Z:z:n:s:hV", long_options, &option_index); if (c == -1) { break; } switch (c) { - case 's': /* -s, --socket */ - spath = strdup(optarg); - break; - - case 'm': /* -m, --map */ - mapname = strdup(optarg); - break; + case 'c': /* -c, --config */ + config_file_name = strndup(optarg, PATH_MAX); + config_file_name_passed = 1; - case 'n': /* -n, --num-threads */ - numThreads = atoi(optarg); + struct stat buffer; - if (numThreads <= 0) { - fprintf(stderr, "Invalid number of threads, must be at least 1\n"); + if (stat(config_file_name, &buffer) != 0) { + g_logger(G_LOG_LEVEL_CRITICAL, "Config file '%s' does not exist, please specify a valid file", config_file_name); return 1; } break; - case 'z': /* -z, --min-zoom */ - minZoom = atoi(optarg); - - if (minZoom < 0 || minZoom > MAX_ZOOM) { - fprintf(stderr, "Invalid minimum zoom selected, must be between 0 and %d\n", MAX_ZOOM); - return 1; - } + case 'm': /* -m, --map */ + mapname = strndup(optarg, XMLCONFIG_MAX); + mapname_passed = 1; + break; + case 'Z': /* -Z, --max-zoom */ + max_zoom = min_max_int_opt(optarg, "maximum zoom", 0, MAX_ZOOM); + max_zoom_passed = 1; break; - case 'Z': /* -Z, --max-zoom */ - maxZoom = atoi(optarg); + case 'z': /* -z, --min-zoom */ + min_zoom = min_max_int_opt(optarg, "minimum zoom", 0, MAX_ZOOM); + min_zoom_passed = 1; + break; - if (maxZoom < 0 || maxZoom > MAX_ZOOM) { - fprintf(stderr, "Invalid maximum zoom selected, must be between 0 and %d\n", MAX_ZOOM); - return 1; - } + case 'n': /* -n, --num-threads */ + num_threads = min_max_int_opt(optarg, "number of threads", 1, -1); + num_threads_passed = 1; + break; + case 's': /* -s, --socket */ + socketname = strndup(optarg, PATH_MAX); + socketname_passed = 1; break; - case 'h': /* -h, --help */ + case 'h': /* -h, --help */ fprintf(stderr, "Usage: render_speedtest [OPTION] ...\n"); - fprintf(stderr, " -m, --map=MAP render tiles in this map (defaults to '%s')\n", XMLCONFIG_DEFAULT); - fprintf(stderr, " -n, --num-threads=N the number of parallel request threads (default 1)\n"); - fprintf(stderr, " -s, --socket=SOCKET|HOSTNAME:PORT unix domain socket name or hostname and port for contacting renderd\n"); - fprintf(stderr, " -Z, --max-zoom=ZOOM only render tiles less than or equal to this zoom level (default is %d)\n", MAX_ZOOM); - fprintf(stderr, " -z, --min-zoom=ZOOM only render tiles greater or equal to this zoom level (default is 0)\n"); + fprintf(stderr, " -c, --config=CONFIG specify the renderd config file (default is off)\n"); + fprintf(stderr, " -m, --map=MAP render tiles in this map (default is '%s')\n", mapname_default); + fprintf(stderr, " -n, --num-threads=N the number of parallel request threads (default is '%d')\n", num_threads_default); + fprintf(stderr, " -s, --socket=SOCKET|HOSTNAME:PORT unix domain socket name or hostname and port for contacting renderd (default is '%s')\n", socketname_default); + fprintf(stderr, " -Z, --max-zoom=ZOOM only render tiles less than or equal to this zoom level (default is '%d')\n", max_zoom_default); + fprintf(stderr, " -z, --min-zoom=ZOOM only render tiles greater than or equal to this zoom level (default is '%d')\n", min_zoom_default); fprintf(stderr, "\n"); fprintf(stderr, " -h, --help display this help and exit\n"); fprintf(stderr, " -V, --version display the version number and exit\n"); - exit(0); + return 0; - case 'V': + case 'V': /* -V, --version */ fprintf(stdout, "%s\n", VERSION); - exit(0); + return 0; default: - fprintf(stderr, "unhandled char '%c'\n", c); - exit(1); + g_logger(G_LOG_LEVEL_CRITICAL, "unhandled char '%c'", c); + return 1; + } + } + + if (max_zoom < min_zoom) { + g_logger(G_LOG_LEVEL_CRITICAL, "Specified min zoom (%i) is larger than max zoom (%i).", min_zoom, max_zoom); + return 1; + } + + if (config_file_name_passed) { + int map_section_num = -1; + process_config_file(config_file_name, 0, G_LOG_LEVEL_DEBUG); + + for (int i = 0; i < XMLCONFIGS_MAX; ++i) { + if (maps[i].xmlname && strcmp(maps[i].xmlname, mapname) == 0) { + map_section_num = i; + } + } + + if (map_section_num < 0) { + g_logger(G_LOG_LEVEL_CRITICAL, "Map section '%s' does not exist in config file '%s'.", mapname, config_file_name); + return 1; + } + + if (!max_zoom_passed) { + max_zoom = maps[map_section_num].max_zoom; + max_zoom_passed = 1; + } + + if (!min_zoom_passed) { + min_zoom = maps[map_section_num].min_zoom; + min_zoom_passed = 1; + } + + if (!num_threads_passed) { + num_threads = maps[map_section_num].num_threads; + num_threads_passed = 1; + } + + if (!socketname_passed) { + socketname = strndup(config.socketname, PATH_MAX); + socketname_passed = 1; } } - static GoogleProjection gprj(maxZoom + 1); + g_logger(G_LOG_LEVEL_INFO, "Started render_speedtest with the following options:"); + + if (config_file_name_passed) { + g_logger(G_LOG_LEVEL_INFO, "\t--config = '%s' (user-specified)", config_file_name); + } + + g_logger(G_LOG_LEVEL_INFO, "\t--map = '%s' (%s)", mapname, mapname_passed ? "user-specified" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--max-zoom = '%i' (%s)", max_zoom, max_zoom_passed ? "user-specified/from config" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--min-zoom = '%i' (%s)", min_zoom, min_zoom_passed ? "user-specified/from config" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--num-threads = '%i' (%s)", num_threads, num_threads_passed ? "user-specified/from config" : "default"); + g_logger(G_LOG_LEVEL_INFO, "\t--socket = '%s' (%s)", socketname, socketname_passed ? "user-specified/from config" : "default"); - fprintf(stderr, "Rendering client\n"); + static GoogleProjection gprj(max_zoom + 1); - spawn_workers(numThreads, spath, 1000); + spawn_workers(num_threads, socketname, 1000); // Render something to counter act the startup costs // of obtaining the Postgis table extents - printf("Initial startup costs\n"); + g_logger(G_LOG_LEVEL_MESSAGE, "Initial startup costs"); gettimeofday(&start, NULL); enqueue(mapname, 0, 0, 0); gettimeofday(&end, NULL); @@ -250,11 +304,12 @@ int main(int argc, char **argv) gettimeofday(&start_all, NULL); - for (z = minZoom; z <= maxZoom; z++) { + for (z = min_zoom; z <= max_zoom; z++) { double px0 = boundx0; double py0 = boundy1; double px1 = boundx1; double py1 = boundy0; + gprj.fromLLtoPixel(px0, py0, z); gprj.fromLLtoPixel(px1, py1, z); @@ -266,13 +321,9 @@ int main(int argc, char **argv) ymin = (int)(py0 / 256.0); ymax = (int)(py1 / 256.0); - num = (xmax - xmin + 1) * (ymax - ymin + 1); -// if (!num) { -// printf("No tiles at zoom(%d)\n", z); -// continue; -// } + int num = (xmax - xmin + 1) * (ymax - ymin + 1); - printf("\nZoom(%d) Now rendering %d tiles\n", z, num); + g_logger(G_LOG_LEVEL_MESSAGE, "Zoom(%d) Now rendering %d tiles", z, num); num_all += num; gettimeofday(&start, NULL); @@ -283,7 +334,6 @@ int main(int argc, char **argv) } wait_for_empty_queue(); - //printf("\n"); gettimeofday(&end, NULL); display_rate(start, end, num); } @@ -291,9 +341,12 @@ int main(int argc, char **argv) finish_workers(); gettimeofday(&end_all, NULL); - printf("\nTotal for all tiles rendered\n"); + g_logger(G_LOG_LEVEL_MESSAGE, "Total for all tiles rendered"); display_rate(start_all, end_all, num_all); - return ret; + free_map_sections(maps); + free_renderd_sections(config_slaves); + + return 0; } #endif diff --git a/src/renderd.c b/src/renderd.c index dda4f710..60075225 100644 --- a/src/renderd.c +++ b/src/renderd.c @@ -96,13 +96,11 @@ static const char *cmdStr(enum protoCmd c) void send_response(struct item *item, enum protoCmd rsp, int render_time) { - struct protocol *req = &item->req; - struct item *prev; - request_queue_remove_request(render_request_queue, item, render_time); while (item) { - req = &item->req; + struct item *prev; + struct protocol *req = &item->req; if ((item->fd != FD_INVALID) && ((req->cmd == cmdRender) || (req->cmd == cmdRenderPrio) || (req->cmd == cmdRenderLow) || (req->cmd == cmdRenderBulk))) { req->cmd = rsp; @@ -337,7 +335,6 @@ void *stats_writeout_thread(void * arg) continue; } else { - noFailedAttempts = 0; fprintf(statfile, "ReqQueueLength: %i\n", reqQueueLength); fprintf(statfile, "ReqPrioQueueLength: %i\n", reqPrioQueueLength); fprintf(statfile, "ReqLowQueueLength: %i\n", reqLowQueueLength); @@ -369,7 +366,7 @@ void *stats_writeout_thread(void * arg) g_logger(G_LOG_LEVEL_WARNING, "Failed to overwrite stats file: %i", errno); noFailedAttempts++; - if (noFailedAttempts > 3) { + if (noFailedAttempts > 6) { g_logger(G_LOG_LEVEL_ERROR, "Failed repeatedly to overwrite stats, giving up"); break; } @@ -744,7 +741,7 @@ int main(int argc, char **argv) } switch (c) { - case 'c': /* -c, --config */ + case 'c': /* -c, --config */ config_file_name = strndup(optarg, PATH_MAX); config_file_name_passed = 1; @@ -757,16 +754,16 @@ int main(int argc, char **argv) break; - case 'f': /* -f, --foreground */ + case 'f': /* -f, --foreground */ foreground = 1; break; - case 's': /* -s, --slave */ + case 's': /* -s, --slave */ active_renderd_section_num = min_max_int_opt(optarg, "active renderd section", 0, -1); active_renderd_section_num_passed = 1; break; - case 'h': /* -h, --help */ + case 'h': /* -h, --help */ fprintf(stderr, "Usage: renderd [OPTION] ...\n"); fprintf(stderr, "Mapnik rendering daemon\n"); fprintf(stderr, " -c, --config=CONFIG specify the renderd config file (default is '%s')\n", config_file_name_default); @@ -777,7 +774,7 @@ int main(int argc, char **argv) fprintf(stderr, " -V, --version display the version number and exit\n"); return 0; - case 'V': /* -V, --version */ + case 'V': /* -V, --version */ fprintf(stdout, "%s\n", VERSION); return 0; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6d671c9a..cbbf99e1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -172,7 +172,31 @@ endfunction() add_test(NAME gen_tile_test COMMAND gen_tile_test - WORKING_DIRECTORY src +) + +add_test( + NAME render_expired_test + COMMAND render_expired_test +) + +add_test( + NAME render_list_test + COMMAND render_list_test +) + +add_test( + NAME render_old_test + COMMAND render_old_test +) + +add_test( + NAME render_speedtest_test + COMMAND render_speedtest_test +) + +add_test( + NAME renderd_test + COMMAND renderd_test ) foreach(STORAGE_BACKEND_INDEX RANGE ${STORAGE_BACKENDS_LENGTH}) @@ -322,6 +346,18 @@ foreach(STORAGE_BACKEND_INDEX RANGE ${STORAGE_BACKENDS_LENGTH}) FIXTURES_REQUIRED services_started_${STORAGE_BACKEND} TIMEOUT 90 ) + add_test(NAME render_expired_config_${SOCKET_TYPE}_${STORAGE_BACKEND} + COMMAND ${BASH} -c " + echo '3/0/3' | $ \ + --config ${RENDERD_CONF} + " + WORKING_DIRECTORY tests + ) + set_tests_properties(render_expired_config_${SOCKET_TYPE}_${STORAGE_BACKEND} PROPERTIES + DEPENDS render_speedtest_${SOCKET_TYPE}_${STORAGE_BACKEND} + FIXTURES_REQUIRED services_started_${STORAGE_BACKEND} + TIMEOUT 60 + ) add_test(NAME render_expired_delete_${SOCKET_TYPE}_${STORAGE_BACKEND} COMMAND ${BASH} -c " echo '0/0/0' | $ \ @@ -382,6 +418,19 @@ foreach(STORAGE_BACKEND_INDEX RANGE ${STORAGE_BACKENDS_LENGTH}) FIXTURES_REQUIRED services_started_${STORAGE_BACKEND} TIMEOUT 90 ) + add_test(NAME render_list_config_${SOCKET_TYPE}_${STORAGE_BACKEND} + COMMAND ${BASH} -c " + $ \ + --all \ + --config ${RENDERD_CONF} + " + WORKING_DIRECTORY tests + ) + set_tests_properties(render_list_config_${SOCKET_TYPE}_${STORAGE_BACKEND} PROPERTIES + DEPENDS render_speedtest_${SOCKET_TYPE}_${STORAGE_BACKEND} + FIXTURES_REQUIRED services_started_${STORAGE_BACKEND} + TIMEOUT 60 + ) add_test(NAME render_list_stdin_${SOCKET_TYPE}_${STORAGE_BACKEND} COMMAND ${BASH} -c " echo '0 0 0' | $ \ @@ -401,6 +450,18 @@ foreach(STORAGE_BACKEND_INDEX RANGE ${STORAGE_BACKENDS_LENGTH}) FIXTURES_REQUIRED services_started_${STORAGE_BACKEND} TIMEOUT 90 ) + add_test(NAME render_list_stdin_config_${SOCKET_TYPE}_${STORAGE_BACKEND} + COMMAND ${BASH} -c " + echo '0 0 0' | $ \ + --config ${RENDERD_CONF} + " + WORKING_DIRECTORY tests + ) + set_tests_properties(render_list_stdin_config_${SOCKET_TYPE}_${STORAGE_BACKEND} PROPERTIES + DEPENDS render_speedtest_${SOCKET_TYPE}_${STORAGE_BACKEND} + FIXTURES_REQUIRED services_started_${STORAGE_BACKEND} + TIMEOUT 60 + ) add_test(NAME render_old_${SOCKET_TYPE}_${STORAGE_BACKEND} COMMAND ${BASH} -c " ${TOUCH_EXECUTABLE} -d '+1 month' ${TEST_TILES_DIR}/planet-import-complete @@ -421,6 +482,32 @@ foreach(STORAGE_BACKEND_INDEX RANGE ${STORAGE_BACKENDS_LENGTH}) FIXTURES_REQUIRED services_started_${STORAGE_BACKEND} TIMEOUT 90 ) + add_test(NAME render_old_config_${SOCKET_TYPE}_${STORAGE_BACKEND} + COMMAND ${BASH} -c " + ${TOUCH_EXECUTABLE} -d '+1 month' ${TEST_TILES_DIR}/planet-import-complete + $ \ + --config ${RENDERD_CONF} + " + WORKING_DIRECTORY tests + ) + set_tests_properties(render_old_config_${SOCKET_TYPE}_${STORAGE_BACKEND} PROPERTIES + DEPENDS render_speedtest_${SOCKET_TYPE}_${STORAGE_BACKEND} + FIXTURES_REQUIRED services_started_${STORAGE_BACKEND} + TIMEOUT 60 + ) + add_test(NAME render_old_config_timestamp_${SOCKET_TYPE}_${STORAGE_BACKEND} + COMMAND ${BASH} -c " + $ \ + --config ${RENDERD_CONF} \ + --timestamp 01/01/2024 + " + WORKING_DIRECTORY tests + ) + set_tests_properties(render_old_config_timestamp_${SOCKET_TYPE}_${STORAGE_BACKEND} PROPERTIES + DEPENDS render_speedtest_${SOCKET_TYPE}_${STORAGE_BACKEND} + FIXTURES_REQUIRED services_started_${STORAGE_BACKEND} + TIMEOUT 60 + ) add_test(NAME render_speedtest_${SOCKET_TYPE}_${STORAGE_BACKEND} COMMAND ${BASH} -c " $ \ @@ -436,6 +523,17 @@ foreach(STORAGE_BACKEND_INDEX RANGE ${STORAGE_BACKENDS_LENGTH}) FIXTURES_REQUIRED "services_started_${STORAGE_BACKEND};tiles_downloaded_${STORAGE_BACKEND}" TIMEOUT 90 ) + add_test(NAME render_speedtest_config_${SOCKET_TYPE}_${STORAGE_BACKEND} + COMMAND ${BASH} -c " + $ \ + --config ${RENDERD_CONF} + " + WORKING_DIRECTORY tests + ) + set_tests_properties(render_speedtest_config_${SOCKET_TYPE}_${STORAGE_BACKEND} PROPERTIES + FIXTURES_REQUIRED "services_started_${STORAGE_BACKEND};tiles_downloaded_${STORAGE_BACKEND}" + TIMEOUT 60 + ) add_test(NAME add_tile_config_${SOCKET_TYPE}_${STORAGE_BACKEND} COMMAND ${BASH} -c " CONFIG_NAME=\"bad_tile_config_${SOCKET_TYPE}\" @@ -1003,3 +1101,108 @@ foreach(DIRECTIVE_INDEX RANGE ${DIRECTIVES_LENGTH}) WORKING_DIRECTORY tests ) endforeach() + + +#----------------------------------------------------------------------------- +# +# Test targets +# +#----------------------------------------------------------------------------- + +#----------------------------------------------------------------------------- +# +# catch_main_o +# +#----------------------------------------------------------------------------- + +add_library(catch_main_o OBJECT + catch/catch_main.cpp + ${PROJECT_SOURCE_DIR}/tests/catch/catch_test_common.cpp +) +target_include_directories(catch_main_o PRIVATE ${GLIB_INCLUDE_DIRS}) + +#----------------------------------------------------------------------------- +# +# catch_test_common_o +# +#----------------------------------------------------------------------------- + +add_library(catch_test_common_o OBJECT ${PROJECT_SOURCE_DIR}/tests/catch/catch_test_common.cpp) +target_include_directories(catch_test_common_o PRIVATE ${GLIB_INCLUDE_DIRS}) + +#----------------------------------------------------------------------------- +# +# gen_tile_test +# +#----------------------------------------------------------------------------- + +# Added by ${PROJECT_SOURCE_DIR}/src/CMakeLists.txt +# (in order to reduce redundant source and library definitions) + +#----------------------------------------------------------------------------- +# +# Additional options for targets added hereafter +# +#----------------------------------------------------------------------------- + +add_compile_definitions( + PROJECT_BINARY_DIR="${PROJECT_BINARY_DIR}/src" + RENDERD_CONF="${PROJECT_SOURCE_DIR}/etc/renderd/renderd.conf" +) +include_directories(${PROJECT_SOURCE_DIR}/includes) +link_libraries(${GLIB_LIBRARIES}) + +#----------------------------------------------------------------------------- +# +# render_expired_test +# +#----------------------------------------------------------------------------- + +add_executable(render_expired_test + $ + render_expired_test.cpp +) + +#----------------------------------------------------------------------------- +# +# render_list_test +# +#----------------------------------------------------------------------------- + +add_executable(render_list_test + $ + render_list_test.cpp +) + +#----------------------------------------------------------------------------- +# +# render_old_test +# +#----------------------------------------------------------------------------- + +add_executable(render_old_test + $ + render_old_test.cpp +) + +#----------------------------------------------------------------------------- +# +# render_speedtest_test +# +#----------------------------------------------------------------------------- + +add_executable(render_speedtest_test + $ + render_speedtest_test.cpp +) + +#----------------------------------------------------------------------------- +# +# renderd_test +# +#----------------------------------------------------------------------------- + +add_executable(renderd_test + $ + renderd_test.cpp +) diff --git a/tests/catch/catch_main.cpp b/tests/catch/catch_main.cpp new file mode 100644 index 00000000..d799da0b --- /dev/null +++ b/tests/catch/catch_main.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2007 - 2023 by mod_tile contributors (see AUTHORS file) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see http://www.gnu.org/licenses/. + */ + +#define CATCH_CONFIG_MAIN + +#include "catch.hpp" +#include "catch_test_common.hpp" + +int foreground = 1; + +struct CaptureListener : Catch::TestEventListenerBase { + + using TestEventListenerBase::TestEventListenerBase; + + void testCaseStarting(Catch::TestCaseInfo const &testCaseInfo) override + { + start_capture(); + } + + void testCaseEnded(Catch::TestCaseStats const &testCaseStats) override + { + bool print = false; + + if (testCaseStats.totals.assertions.failed > 0) { + print = true; + } + + end_capture(print); + } +}; + +CATCH_REGISTER_LISTENER(CaptureListener) diff --git a/tests/catch/catch_test_common.cpp b/tests/catch/catch_test_common.cpp new file mode 100644 index 00000000..3e8751d8 --- /dev/null +++ b/tests/catch/catch_test_common.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2007 - 2023 by mod_tile contributors (see AUTHORS file) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see http://www.gnu.org/licenses/. + */ + +#include +#include +#include +#include +#include +#include +#include + +extern int foreground; + +typedef struct _captured_stdio { + int temp_fd; + int pipes[2]; +} captured_stdio; + +captured_stdio captured_stderr; +captured_stdio captured_stdout; + +void capture_stderr() +{ + // Flush stderr first if you've previously printed something + fflush(stderr); + + // Save stderr so it can be restored later + int temp_stderr; + temp_stderr = dup(fileno(stderr)); + + // Redirect stderr to a new pipe + int pipes[2]; + pipe(pipes); + dup2(pipes[1], fileno(stderr)); + + captured_stderr.temp_fd = temp_stderr; + captured_stderr.pipes[0] = pipes[0]; + captured_stderr.pipes[1] = pipes[1]; +} + +std::string get_captured_stderr(bool print = false) +{ + // Terminate captured output with a zero + write(captured_stderr.pipes[1], "", 1); + + // Restore stderr + fflush(stderr); + dup2(captured_stderr.temp_fd, fileno(stderr)); + + // Save & return the captured output + std::string log_lines; + const int buffer_size = 4096; + char buffer[buffer_size]; + read(captured_stderr.pipes[0], buffer, buffer_size); + log_lines += buffer; + + if (print) { + std::cout << "err_log_lines: " << log_lines << "\n"; + } + + return log_lines; +} + +void capture_stdout() +{ + // Flush stdout first if you've previously printed something + fflush(stdout); + + // Save stdout so it can be restored later + int temp_stdout; + temp_stdout = dup(fileno(stdout)); + + // Redirect stdout to a new pipe + int pipes[2]; + pipe(pipes); + dup2(pipes[1], fileno(stdout)); + + captured_stdout.temp_fd = temp_stdout; + captured_stdout.pipes[0] = pipes[0]; + captured_stdout.pipes[1] = pipes[1]; +} + +std::string get_captured_stdout(bool print = false) +{ + // Terminate captured output with a zero + write(captured_stdout.pipes[1], "", 1); + + // Restore stdout + fflush(stdout); + dup2(captured_stdout.temp_fd, fileno(stdout)); + + // Save & return the captured output + std::string log_lines; + const int buffer_size = 4096; + char buffer[buffer_size]; + read(captured_stdout.pipes[0], buffer, buffer_size); + log_lines += buffer; + + if (print) { + std::cout << "out_log_lines: " << log_lines << "\n"; + } + + return log_lines; +} + +void start_capture(bool debug = false) +{ + foreground = debug ? 1 : 0; + + if (debug) { + setenv("G_MESSAGES_DEBUG", "all", 1); +#if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 79 + // https://gitlab.gnome.org/GNOME/glib/-/merge_requests/3710 + std::cout << "Resetting G_MESSAGES_DEBUG env var in runtime no longer has an effect.\n"; + const gchar *domains[] = {"all", NULL}; + g_log_writer_default_set_debug_domains(domains); +#endif + } + + capture_stderr(); + capture_stdout(); +} + +std::tuple end_capture(bool print = false) +{ + setenv("G_MESSAGES_DEBUG", "", 1); +#if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 79 + g_log_writer_default_set_debug_domains(NULL); +#endif + foreground = 0; + + return std::tuple(get_captured_stderr(print), get_captured_stdout(print)); +} diff --git a/tests/catch/catch_test_common.hpp b/tests/catch/catch_test_common.hpp new file mode 100644 index 00000000..2e4aebd3 --- /dev/null +++ b/tests/catch/catch_test_common.hpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2007 - 2023 by mod_tile contributors (see AUTHORS file) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see http://www.gnu.org/licenses/. + */ + +#include + +#ifndef CATCH_TEST_COMMON_HPP +#define CATCH_TEST_COMMON_HPP + +void capture_stderr(); +void capture_stdout(); + +std::string get_captured_stderr(bool print = false); +std::string get_captured_stdout(bool print = false); + +void start_capture(bool debug = false); +std::tuple end_capture(bool print = false); + +#endif diff --git a/tests/gen_tile_test.cpp b/tests/gen_tile_test.cpp index 7f8653f4..536b270c 100644 --- a/tests/gen_tile_test.cpp +++ b/tests/gen_tile_test.cpp @@ -37,6 +37,7 @@ #include #include "catch/catch.hpp" +#include "catch/catch_test_common.hpp" #include "config.h" #include "g_logger.h" #include "gen_tile.h" @@ -49,14 +50,6 @@ #include "store.h" #include "string.h" -#ifdef __MACH__ -#include -#include -#endif -#ifdef __FreeBSD__ -#include -#endif - #if MAPNIK_MAJOR_VERSION >= 4 #include #else @@ -73,129 +66,6 @@ extern mapnik::box2d tile2prjbounds(struct projectionconfig *prj, int x, // mutex to guard access to the shared render request counter static pthread_mutex_t item_counter_lock; -typedef struct _captured_stdio { - int temp_fd; - int pipes[2]; -} captured_stdio; - -captured_stdio captured_stderr; -captured_stdio captured_stdout; - -void capture_stderr() -{ - // Flush stderr first if you've previously printed something - fflush(stderr); - - // Save stderr so it can be restored later - int temp_stderr; - temp_stderr = dup(fileno(stderr)); - - // Redirect stderr to a new pipe - int pipes[2]; - pipe(pipes); - dup2(pipes[1], fileno(stderr)); - - captured_stderr.temp_fd = temp_stderr; - captured_stderr.pipes[0] = pipes[0]; - captured_stderr.pipes[1] = pipes[1]; -} - -std::string get_captured_stderr(bool print = false) -{ - // Terminate captured output with a zero - write(captured_stderr.pipes[1], "", 1); - - // Restore stderr - fflush(stderr); - dup2(captured_stderr.temp_fd, fileno(stderr)); - - // Save & return the captured output - std::string log_lines; - const int buffer_size = 1024; - char buffer[buffer_size]; - read(captured_stderr.pipes[0], buffer, buffer_size); - log_lines += buffer; - - if (print) { - std::cout << "err_log_lines: " << log_lines << "\n"; - } - - return log_lines; -} - -void capture_stdout() -{ - // Flush stdout first if you've previously printed something - fflush(stdout); - - // Save stdout so it can be restored later - int temp_stdout; - temp_stdout = dup(fileno(stdout)); - - // Redirect stdout to a new pipe - int pipes[2]; - pipe(pipes); - dup2(pipes[1], fileno(stdout)); - - captured_stdout.temp_fd = temp_stdout; - captured_stdout.pipes[0] = pipes[0]; - captured_stdout.pipes[1] = pipes[1]; -} - -std::string get_captured_stdout(bool print = false) -{ - // Terminate captured output with a zero - write(captured_stdout.pipes[1], "", 1); - - // Restore stdout - fflush(stdout); - dup2(captured_stdout.temp_fd, fileno(stdout)); - - // Save & return the captured output - std::string log_lines; - const int buffer_size = 1024; - char buffer[buffer_size]; - read(captured_stdout.pipes[0], buffer, buffer_size); - log_lines += buffer; - - if (print) { - std::cout << "out_log_lines: " << log_lines << "\n"; - } - - return log_lines; -} - -void start_capture(bool debug = false) -{ - foreground = debug ? 1 : 0; - - if (debug) { -#if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION == 79 - // https://gitlab.gnome.org/GNOME/glib/-/merge_requests/3710 - std::cout << "Resetting G_MESSAGES_DEBUG env var in runtime no longer has an effect.\n"; - const gchar *domains[] = {"all", NULL}; - g_log_writer_default_set_debug_domains(domains); -#else - setenv("G_MESSAGES_DEBUG", "all", 1); -#endif - } - - capture_stderr(); - capture_stdout(); -} - -std::tuple end_capture(bool print = false) -{ -#if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION == 79 - g_log_writer_default_set_debug_domains(NULL); -#else - setenv("G_MESSAGES_DEBUG", "", 1); -#endif - foreground = 0; - - return std::tuple(get_captured_stderr(print), get_captured_stdout(print)); -} - struct item *init_render_request(enum protoCmd type) { static int counter; @@ -266,221 +136,6 @@ int delete_tile_dir(std::string tile_dir) return rmdir(tile_dir.c_str()); } -TEST_CASE("render_expired", "render expired") -{ - SECTION("render_expired startup --help", "should start and show help message") { - // flawfinder: ignore - int ret = system("./render_expired -h"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 0); - } - - SECTION("render_expired startup --version", "should start and show version number") { - // flawfinder: ignore - FILE *pipe = popen("./render_expired -V", "r"); - std::string output; - char buffer[sizeof(VERSION)]; - fgets(buffer, sizeof(buffer), pipe); - output += buffer; - pclose(pipe); - REQUIRE(output == VERSION); - } - - SECTION("render_expired startup unrecognized option", "should return 1") { - // flawfinder: ignore - int ret = system("./render_expired --doesnotexit"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } - - SECTION("render_expired startup invalid option", "should return 1") { - // flawfinder: ignore - int ret = system("./render_expired -oesnotexit"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } -} - -TEST_CASE("render_list", "render list") -{ - SECTION("render_list startup --help", "should start and show help message") { - // flawfinder: ignore - int ret = system("./render_list -h"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 0); - } - - SECTION("render_list startup --version", "should start and show version number") { - // flawfinder: ignore - FILE *pipe = popen("./render_list -V", "r"); - std::string output; - char buffer[sizeof(VERSION)]; - fgets(buffer, sizeof(buffer), pipe); - output += buffer; - pclose(pipe); - REQUIRE(output == VERSION); - } - - SECTION("render_list startup unrecognized option", "should return 1") { - // flawfinder: ignore - int ret = system("./render_list --doesnotexit"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } - - SECTION("render_list startup invalid option", "should return 1") { - // flawfinder: ignore - int ret = system("./render_list -doesnotexit"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } - - SECTION("render_list option is positive with --help", "should return 0") { - std::string option = GENERATE("--max-load", "--max-x", "--max-y", "--max-zoom", "--min-x", "--min-y", "--min-zoom", "--num-threads"); - std::string command = "./render_list " + option + " 1 --help"; - - // flawfinder: ignore - int ret = system(command.c_str()); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 0); - } - - SECTION("render_list option is negative", "should return 1") { - std::string option = GENERATE("--max-load", "--max-x", "--max-y", "--max-zoom", "--min-x", "--min-y", "--min-zoom", "--num-threads"); - std::string command = "./render_list " + option + " -1"; - - // flawfinder: ignore - int ret = system(command.c_str()); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } - - SECTION("render_list option is float", "should return 1") { - std::string option = GENERATE("--max-load", "--max-x", "--max-y", "--max-zoom", "--min-x", "--min-y", "--min-zoom", "--num-threads"); - std::string command = "./render_list " + option + " 0.12345"; - - // flawfinder: ignore - int ret = system(command.c_str()); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } - - SECTION("render_list num threads subceeds minimum of 1", "should return 1") { - // flawfinder: ignore - int ret = system("./render_list -n 0"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } - - SECTION("render_list zoom exceeds maximum of MAX_ZOOM", "should return 1") { - std::string option = GENERATE("--max-zoom", "--min-zoom"); - std::string command = "./render_list " + option + " 1000"; - - // flawfinder: ignore - int ret = system(command.c_str()); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } - - SECTION("render_list min zoom exceeds max zoom", "should return 1") { - // flawfinder: ignore - int ret = system("./render_list -z 10 -Z 9"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } - - SECTION("render_list all min zoom not equal to max zoom with X/Y options", "should return 1") { - // flawfinder: ignore - int ret = system("./render_list -z 9 -Z 10 -a -X 1 -Y 1"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } - - SECTION("render_list all max x/y options exceed maximum (2^zoom-1)", "should return 1") { - // flawfinder: ignore - int ret = system("./render_list -z 1 -Z 1 -a -X 2 -Y 2"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } - - SECTION("render_list all min x/y options exceed maximum (2^zoom-1)", "should return 1") { - // flawfinder: ignore - int ret = system("./render_list -z 1 -Z 1 -a -x 2 -y 2"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } -} - -TEST_CASE("render_old", "render old") -{ - SECTION("render_old startup --help", "should start and show help message") { - // flawfinder: ignore - int ret = system("./render_old -h"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 0); - } - - SECTION("render_old startup --version", "should start and show version number") { - // flawfinder: ignore - FILE *pipe = popen("./render_old -V", "r"); - std::string output; - char buffer[sizeof(VERSION)]; - fgets(buffer, sizeof(buffer), pipe); - output += buffer; - pclose(pipe); - REQUIRE(output == VERSION); - } - - SECTION("render_old startup unrecognized option", "should return 1") { - // flawfinder: ignore - int ret = system("./render_old --doesnotexit"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } - - SECTION("render_old startup invalid option", "should return 1") { - // flawfinder: ignore - int ret = system("./render_old -doesnotexit"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } -} - -TEST_CASE("render_speedtest", "render speed test") -{ - SECTION("render_speedtest startup --help", "should start and show help message") { - // flawfinder: ignore - int ret = system("./render_speedtest -h"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 0); - } - - SECTION("render_speedtest startup --version", "should start and show version number") { - // flawfinder: ignore - FILE *pipe = popen("./render_speedtest -V", "r"); - std::string output; - char buffer[sizeof(VERSION)]; - fgets(buffer, sizeof(buffer), pipe); - output += buffer; - pclose(pipe); - REQUIRE(output == VERSION); - } - - SECTION("render_speedtest startup unrecognized option", "should return 1") { - // flawfinder: ignore - int ret = system("./render_speedtest --doesnotexit"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } - - SECTION("render_speedtest startup invalid option", "should return 1") { - // flawfinder: ignore - int ret = system("./render_speedtest -doesnotexit"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } -} - TEST_CASE("renderd/queueing", "request queueing") { SECTION("renderd/queueing/initialisation", "test the initialisation of the request queue") { @@ -1005,85 +660,6 @@ TEST_CASE("renderd", "tile generation") request_queue_close(render_request_queue); SUCCEED(); } - - SECTION("renderd startup --help", "should start and show help message") { - // flawfinder: ignore - int ret = system("./renderd -h"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 0); - } - - SECTION("renderd startup --version", "should start and show version number") { - // flawfinder: ignore - FILE *pipe = popen("./renderd -V", "r"); - std::string output; - char buffer[sizeof(VERSION)]; - fgets(buffer, sizeof(buffer), pipe); - output += buffer; - pclose(pipe); - REQUIRE(output == VERSION); - } - - SECTION("renderd startup --config fakefile.conf --foreground", "should not start and return 1") { - // flawfinder: ignore - int ret = system("./renderd -c fakefile.conf -f"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } - - SECTION("renderd startup unrecognized option", "should return 1") { - // flawfinder: ignore - int ret = system("./renderd --doesnotexit"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } - - SECTION("renderd startup invalid option", "should return 1") { - // flawfinder: ignore - int ret = system("./renderd -doesnotexit"); - ret = WEXITSTATUS(ret); - REQUIRE(ret == 1); - } - - SECTION("--config invalid file", "should return 1") { - std::string option = "--config /path/is/invalid"; - std::string command = "./renderd " + option; - - // flawfinder: ignore - FILE *pipe = popen(command.c_str(), "r"); - int status = pclose(pipe); - REQUIRE(WEXITSTATUS(status) == 1); - } - - SECTION("--slave is not a number", "should return 1") { - std::string option = "--slave abcdefg"; - std::string command = "./renderd " + option; - - // flawfinder: ignore - FILE *pipe = popen(command.c_str(), "r"); - int status = pclose(pipe); - REQUIRE(WEXITSTATUS(status) == 1); - } - - SECTION("--slave is a float", "should return 1") { - std::string option = "--slave 1.23456789"; - std::string command = "./renderd " + option; - - // flawfinder: ignore - FILE *pipe = popen(command.c_str(), "r"); - int status = pclose(pipe); - REQUIRE(WEXITSTATUS(status) == 1); - } - - SECTION("--slave subceeds minimum of 0", "should return 1") { - std::string option = "--slave -1"; - std::string command = "./renderd " + option; - - // flawfinder: ignore - FILE *pipe = popen(command.c_str(), "r"); - int status = pclose(pipe); - REQUIRE(WEXITSTATUS(status) == 1); - } } TEST_CASE("storage-backend", "Tile storage backend router") diff --git a/tests/render_expired_test.cpp b/tests/render_expired_test.cpp new file mode 100644 index 00000000..5437158b --- /dev/null +++ b/tests/render_expired_test.cpp @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2007 - 2023 by mod_tile contributors (see AUTHORS file) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see http://www.gnu.org/licenses/. + */ + +#include +#include +#include + +#include "catch/catch.hpp" +#include "config.h" +#include "render_config.h" + +#ifdef __FreeBSD__ +#include +#endif + +#ifndef PROJECT_BINARY_DIR +#define PROJECT_BINARY_DIR "." +#endif + +#ifndef RENDERD_CONF +#define RENDERD_CONF "./etc/renderd/renderd.conf" +#endif + +std::string test_binary = (std::string)PROJECT_BINARY_DIR + "/" + "render_expired"; + +TEST_CASE("render_expired common", "common testing") +{ + SECTION("invalid long option", "should return 1") { + std::string option = "--doesnotexist"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("invalid short options", "should return 1") { + std::string option = "-oesnotexist"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--help", "should return 0") { + std::string option = "--help"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("--version", "should show version number") { + std::string option = "--version"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + std::string output; + char buffer[sizeof(VERSION)]; + fgets(buffer, sizeof(buffer), pipe); + output += buffer; + REQUIRE(output == VERSION); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("--config invalid file", "should return 1") { + std::string option = "--config /path/is/invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } +} + +TEST_CASE("render_expired specific", "specific testing") +{ + SECTION("--num-threads subceeds minimum of 1", "should return 1") { + std::string option = "--num-threads 0"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--min-zoom/--max-zoom exceeds maximum of MAX_ZOOM", "should return 1") { + std::string option = GENERATE("--max-zoom", "--min-zoom"); + std::string command = test_binary + " " + option + " " + std::to_string(MAX_ZOOM + 1); + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--min-zoom exceeds --max-zoom", "should return 1") { + std::string option = "--max-zoom " + std::to_string(MAX_ZOOM - 2) + " --min-zoom " + std::to_string(MAX_ZOOM - 1); + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--config without maps", "should return 1") { + std::string option = "--config " + (std::string)RENDERD_CONF; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--config with invalid --map", "should return 1") { + std::string renderd_conf_examples = (std::string)RENDERD_CONF + ".examples"; + std::string option = "--config " + renderd_conf_examples + " --map invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--config with valid --map and --tile-dir with invalid path", "should return 1") { + std::string renderd_conf_examples = (std::string)RENDERD_CONF + ".examples"; + std::string option = "--config " + renderd_conf_examples + " --map example-map --tile-dir /path/is/invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--config with valid --map, --verbose and bad input lines", "should return 0") { + std::string renderd_conf_examples = (std::string)RENDERD_CONF + ".examples"; + std::string option = "--config " + renderd_conf_examples + " --map example-map --tile-dir " + P_tmpdir + " --verbose"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "w"); + fputs("z/x/y\n", pipe); + fputs("x y z\n", pipe); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("--tile-dir with invalid option", "should return 1") { + std::string option = "--tile-dir invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--tile-dir with invalid path", "should return 1") { + std::string option = "--tile-dir /path/is/invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } +} + +TEST_CASE("render_expired generator", "generator testing") +{ + std::string option = GENERATE("--delete-from", "--max-load", "--max-zoom", "--min-zoom", "--num-threads", "--touch-from"); + + SECTION("option is positive with --help", "should return 0") { + std::string command = test_binary + " " + option + " 1 --help"; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("option is negative", "should return 1") { + std::string command = test_binary + " " + option + " -1"; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("option is float", "should return 1") { + std::string command = test_binary + " " + option + " 1.23456789"; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } +} diff --git a/tests/render_list_test.cpp b/tests/render_list_test.cpp new file mode 100644 index 00000000..581e1947 --- /dev/null +++ b/tests/render_list_test.cpp @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2007 - 2023 by mod_tile contributors (see AUTHORS file) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see http://www.gnu.org/licenses/. + */ + +#include +#include +#include + +#include "catch/catch.hpp" +#include "config.h" +#include "render_config.h" + +#ifdef __FreeBSD__ +#include +#endif + +#ifndef PROJECT_BINARY_DIR +#define PROJECT_BINARY_DIR "." +#endif + +#ifndef RENDERD_CONF +#define RENDERD_CONF "./etc/renderd/renderd.conf" +#endif + +std::string test_binary = (std::string)PROJECT_BINARY_DIR + "/" + "render_list"; + +TEST_CASE("render_list common", "common testing") +{ + SECTION("invalid long option", "should return 1") { + std::string option = "--doesnotexist"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("invalid short options", "should return 1") { + std::string option = "-doesnotexist"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--help", "should return 0") { + std::string option = "--help"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("--version", "should show version number") { + std::string option = "--version"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + std::string output; + char buffer[sizeof(VERSION)]; + fgets(buffer, sizeof(buffer), pipe); + output += buffer; + REQUIRE(output == VERSION); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("--config invalid file", "should return 1") { + std::string option = "--config /path/is/invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } +} + +TEST_CASE("render_list specific", "specific testing") +{ + SECTION("--num-threads subceeds minimum of 1", "should return 1") { + std::string option = "--num-threads 0"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--min-zoom/--max-zoom exceeds maximum of MAX_ZOOM", "should return 1") { + std::string option = GENERATE("--max-zoom", "--min-zoom"); + std::string command = test_binary + " " + option + " " + std::to_string(MAX_ZOOM + 1); + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--min-zoom exceeds --max-zoom", "should return 1") { + std::string option = "--max-zoom " + std::to_string(MAX_ZOOM - 2) + " --min-zoom " + std::to_string(MAX_ZOOM - 1); + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--all --min-zoom not equal to --max-zoom with X/Y options", "should return 1") { + std::string option = "--all --max-x 1 --max-zoom 10 --max-y 1 --min-zoom 9"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--all --max-x/y options exceed maximum (2^zoom-1)", "should return 1") { + std::string option = "--all --max-x 2 --max-y 2 --max-zoom 1 --min-zoom 1"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--all --min-x/y options exceed maximum (2^zoom-1)", "should return 1") { + std::string option = "--all --max-zoom 1 --min-x 2 --min-y 2 --min-zoom 1"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--config without maps", "should return 1") { + std::string option = "--config " + (std::string)RENDERD_CONF; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--config with invalid --map", "should return 1") { + std::string renderd_conf_examples = (std::string)RENDERD_CONF + ".examples"; + std::string option = "--config " + renderd_conf_examples + " --map invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--config with valid --map and --tile-dir with invalid path", "should return 1") { + std::string renderd_conf_examples = (std::string)RENDERD_CONF + ".examples"; + std::string option = "--config " + renderd_conf_examples + " --map example-map --tile-dir /path/is/invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--config with valid --map, --verbose and bad input lines", "should return 0") { + std::string renderd_conf_examples = (std::string)RENDERD_CONF + ".examples"; + std::string option = "--config " + renderd_conf_examples + " --map example-map --tile-dir " + P_tmpdir + " --verbose"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "w"); + fputs("z/x/y\n", pipe); + fputs("x y z\n", pipe); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("--config with valid --map, --verbose and invalid zoom input lines", "should return 0") { + std::string renderd_conf_examples = (std::string)RENDERD_CONF + ".examples"; + std::string option = "--config " + renderd_conf_examples + " --map example-map --tile-dir " + P_tmpdir + " --verbose"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "w"); + fputs("0 0 -100\n", pipe); + fputs("0 0 100\n", pipe); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("--tile-dir with invalid option", "should return 1") { + std::string option = "--tile-dir invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--tile-dir with invalid path", "should return 1") { + std::string option = "--tile-dir /path/is/invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } +} + +TEST_CASE("render_list generator", "generator testing") +{ + std::string option = GENERATE("--max-load", "--max-x", "--max-y", "--max-zoom", "--min-x", "--min-y", "--min-zoom", "--num-threads"); + + SECTION("option is positive with --help", "should return 0") { + std::string command = test_binary + " " + option + " 1 --help"; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("option is negative", "should return 1") { + std::string command = test_binary + " " + option + " -1"; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("option is float", "should return 1") { + std::string command = test_binary + " " + option + " 1.23456789"; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } +} diff --git a/tests/render_old_test.cpp b/tests/render_old_test.cpp new file mode 100644 index 00000000..cb5205cc --- /dev/null +++ b/tests/render_old_test.cpp @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2007 - 2023 by mod_tile contributors (see AUTHORS file) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see http://www.gnu.org/licenses/. + */ + +#include +#include +#include + +#include "catch/catch.hpp" +#include "config.h" +#include "render_config.h" + +#ifdef __FreeBSD__ +#include +#endif + +#ifndef PROJECT_BINARY_DIR +#define PROJECT_BINARY_DIR "." +#endif + +#ifndef RENDERD_CONF +#define RENDERD_CONF "./etc/renderd/renderd.conf" +#endif + +std::string test_binary = (std::string)PROJECT_BINARY_DIR + "/" + "render_old"; + +TEST_CASE("render_old common", "common testing") +{ + SECTION("invalid long option", "should return 1") { + std::string option = "--doesnotexist"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("invalid short options", "should return 1") { + std::string option = "-doesnotexist"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--help", "should return 0") { + std::string option = "--help"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("--version", "should show version number") { + std::string option = "--version"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + std::string output; + char buffer[sizeof(VERSION)]; + fgets(buffer, sizeof(buffer), pipe); + output += buffer; + REQUIRE(output == VERSION); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("--config invalid file", "should return 1") { + std::string option = "--config /path/is/invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } +} + +TEST_CASE("render_old specific", "specific testing") +{ + SECTION("--num-threads subceeds minimum of 1", "should return 1") { + std::string option = "--num-threads 0"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--min-zoom/--max-zoom exceeds maximum of MAX_ZOOM", "should return 1") { + std::string option = GENERATE("--max-zoom", "--min-zoom"); + std::string command = test_binary + " " + option + " " + std::to_string(MAX_ZOOM + 1); + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--min-zoom exceeds --max-zoom", "should return 1") { + std::string option = "--max-zoom " + std::to_string(MAX_ZOOM - 2) + " --min-zoom " + std::to_string(MAX_ZOOM - 1); + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--timestamp is not an integer", "should return 1") { + std::string option = "--timestamp invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--timestamp is a date with --help", "should return 0") { + std::string option = GENERATE("--timestamp 01/01/01", "--timestamp 01/01/1901"); + std::string command = test_binary + " " + option + " --help"; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("--timestamp is an integer with --help", "should return 0") { + std::string option = "--timestamp 111 --help"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("--config without maps", "should return 1") { + std::string option = "--config " + (std::string)RENDERD_CONF; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--config with invalid --map", "should return 1") { + std::string renderd_conf_examples = (std::string)RENDERD_CONF + ".examples"; + std::string option = "--config " + renderd_conf_examples + " --map invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } +} + +TEST_CASE("render_old generator", "generator testing") +{ + std::string option = GENERATE("--max-load", "--max-zoom", "--min-zoom", "--num-threads"); + + SECTION("option is positive with --help", "should return 0") { + std::string command = test_binary + " " + option + " 1 --help"; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("option is negative", "should return 1") { + std::string command = test_binary + " " + option + " -1"; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("option is float", "should return 1") { + std::string command = test_binary + " " + option + " 1.23456789"; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } +} diff --git a/tests/render_speedtest_test.cpp b/tests/render_speedtest_test.cpp new file mode 100644 index 00000000..0e913665 --- /dev/null +++ b/tests/render_speedtest_test.cpp @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2007 - 2023 by mod_tile contributors (see AUTHORS file) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see http://www.gnu.org/licenses/. + */ + +#include +#include +#include + +#include "catch/catch.hpp" +#include "config.h" +#include "render_config.h" + +#ifdef __FreeBSD__ +#include +#endif + +#ifndef PROJECT_BINARY_DIR +#define PROJECT_BINARY_DIR "." +#endif + +#ifndef RENDERD_CONF +#define RENDERD_CONF "./etc/renderd/renderd.conf" +#endif + +std::string test_binary = (std::string)PROJECT_BINARY_DIR + "/" + "render_speedtest"; + +TEST_CASE("render_speedtest common", "common testing") +{ + SECTION("invalid long option", "should return 1") { + std::string option = "--doesnotexist"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("invalid short options", "should return 1") { + std::string option = "-doesnotexist"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--help", "should return 0") { + std::string option = "--help"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("--version", "should show version number") { + std::string option = "--version"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + std::string output; + char buffer[sizeof(VERSION)]; + fgets(buffer, sizeof(buffer), pipe); + output += buffer; + REQUIRE(output == VERSION); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("--config invalid file", "should return 1") { + std::string option = "--config /path/is/invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } +} + +TEST_CASE("render_speedtest specific", "specific testing") +{ + SECTION("--num-threads subceeds minimum of 1", "should return 1") { + std::string option = "--num-threads 0"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--min-zoom/--max-zoom exceeds maximum of MAX_ZOOM", "should return 1") { + std::string option = GENERATE("--max-zoom", "--min-zoom"); + std::string command = test_binary + " " + option + " " + std::to_string(MAX_ZOOM + 1); + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--min-zoom exceeds --max-zoom", "should return 1") { + std::string option = "--max-zoom " + std::to_string(MAX_ZOOM - 2) + " --min-zoom " + std::to_string(MAX_ZOOM - 1); + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--config without maps", "should return 1") { + std::string option = "--config " + (std::string)RENDERD_CONF; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--config with invalid --map", "should return 1") { + std::string renderd_conf_examples = (std::string)RENDERD_CONF + ".examples"; + std::string option = "--config " + renderd_conf_examples + " --map invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--config with valid --map and --tile-dir with invalid path", "should return 1") { + std::string renderd_conf_examples = (std::string)RENDERD_CONF + ".examples"; + std::string option = "--config " + renderd_conf_examples + " --map example-map --tile-dir /path/is/invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--tile-dir with invalid option", "should return 1") { + std::string option = "--tile-dir invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--tile-dir with invalid path", "should return 1") { + std::string option = "--tile-dir /path/is/invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } +} + +TEST_CASE("render_speedtest generator", "generator testing") +{ + std::string option = GENERATE("--max-zoom", "--min-zoom", "--num-threads"); + + SECTION("option is positive with --help", "should return 0") { + std::string command = test_binary + " " + option + " 1 --help"; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("option is negative", "should return 1") { + std::string command = test_binary + " " + option + " -1"; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("option is float", "should return 1") { + std::string command = test_binary + " " + option + " 1.23456789"; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } +} diff --git a/tests/renderd_test.cpp b/tests/renderd_test.cpp new file mode 100644 index 00000000..2837ab2b --- /dev/null +++ b/tests/renderd_test.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2007 - 2023 by mod_tile contributors (see AUTHORS file) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see http://www.gnu.org/licenses/. + */ + +#include +#include +#include + +#include "catch/catch.hpp" +#include "config.h" + +#ifdef __FreeBSD__ +#include +#endif + +#ifndef PROJECT_BINARY_DIR +#define PROJECT_BINARY_DIR "." +#endif + +#ifndef RENDERD_CONF +#define RENDERD_CONF "./etc/renderd/renderd.conf" +#endif + +std::string test_binary = (std::string)PROJECT_BINARY_DIR + "/" + "renderd"; + +TEST_CASE("renderd common", "common testing") +{ + SECTION("invalid long option", "should return 1") { + std::string option = "--doesnotexist"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("invalid short options", "should return 1") { + std::string option = "-doesnotexist"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } + + SECTION("--help", "should return 0") { + std::string option = "--help"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("--version", "should show version number") { + std::string option = "--version"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + std::string output; + char buffer[sizeof(VERSION)]; + fgets(buffer, sizeof(buffer), pipe); + output += buffer; + REQUIRE(output == VERSION); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 0); + } + + SECTION("--config invalid file", "should return 1") { + std::string option = "--config /path/is/invalid"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } +} + +TEST_CASE("renderd specific", "specific testing") +{ + SECTION("--slave subceeds minimum of 0", "should return 1") { + std::string option = "--slave -1"; + std::string command = test_binary + " " + option; + + // flawfinder: ignore + FILE *pipe = popen(command.c_str(), "r"); + int status = pclose(pipe); + REQUIRE(WEXITSTATUS(status) == 1); + } +}