1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
|
# Overview
# --------
#
# This is a non-recursive Makefile for running vifm tests using stic.
#
# Vifm is built before running any tests as its object files are used for tests.
# Necessary include and link directives are picked up from the main Makefile.
#
# Each test-suite (directory) is run in a separate sandbox directory. During
# compilation two defines are available:
# - TEST_DATA_PATH -- path to test-data/ directory (might be RO)
# - SANDBOX_PATH -- path to sandbox for the suite (always RW)
#
# Test suites can be run concurrently.
#
# Usage
# -----
#
# By default tests are built in release mode.
#
# make -- builds and runs all tests
# make build -- builds all tests without running them
# make check -- builds all tests and then runs them
# make <dir> -- runs specific test suite
# make <dir>.<name> -- runs specific fixture
#
# make DEBUG=1 ... -- builds debug version
# make DEBUG=gdb ... -- builds debug version and loads suite into gdb
# make DEBUG=rr ... -- builds debug version and loads suite into rr
# make DEBUG=valgrind ... -- builds debug version and runs it under valgrind
# (see valgrind-report file after a run)
#
# make VERBOSE=1 ... -- enables verbose printing of commands
#
# make TEST_RUN_PREFIX=wine -- sets run command prefix
#
# make clean -- removes various build artifacts
#
# make TESTS_CFLAGS=... TESTS_LDFLAGS... -- prepend something to CFLAGS/LDFLAGS
#
# "B" variable might be set to build tree root to run tests out of the source
# tree.
# don't undefine $TERM if we're going to invoke gdb or it will prevent its TUI
# from starting
ifneq ($(DEBUG),gdb)
# don't pass $TERM to tests, they should work without a terminal and this
# variable
unexport TERM
endif
# hide terminal multiplexers and graphic systems, so tests behave consistently
unexport STY TMUX DISPLAY WAYLAND_DISPLAY
# determine kind of OS that is running
ifeq ($(OS),Windows_NT)
ifeq ($(shell uname -o 2> /dev/null),Cygwin)
unix_env := true
else
win_env := true
endif
else
ifeq ($(CROSS),)
ifeq ($(shell id -u),0)
$(warning warning: running tests as root disables chmod-based ones)
endif
unix_env := true
else
win_env := true
endif
endif
ifdef DEBUG
BINSUBDIR := debug/
endif
# test for a bad directory path which breaks the Makefile
ifndef win_env
# testing for # seems to work only for some versions of GNU Make
ifneq (,$(findstring :,$(PWD)))
$(error Paths with : break tests' Makefile)
endif
endif
# path to build tree
B ?=
# path to storage for intermediate build files
BUILD := $(B)bin/build/$(BINSUBDIR)
# engine
suites += abbrevs autocmds cmds commands completion keys options parsing
suites += text_buffer variables
# io
suites += ioeta ionotif iop ior
# ui
suites += colmgr column_view viewcolumns_parser
# everything else
suites += bmarks escape fileops filetype filter lua menus misc undo utils
# these are built, but not automatically executed
apps := fuzz io_tester_app regs_shmem_app
# obtain list of sources that are being tested
vifm_src := ./ cfg/ compat/ engine/ int/ io/ io/private/ lua/ lua/lua/ menus/
vifm_src += modes/ modes/dialogs/ ui/ utils/
vifm_src := $(wildcard $(addprefix ../src/, $(addsuffix *.c, $(vifm_src))))
vifm_src := $(filter-out %/tags.c %/xxhash.c, $(vifm_src))
# filter out generally non-testable or sources for another platform
vifm_src := $(filter-out %/src/./vifm.c %/win_helper.c, $(vifm_src))
ifndef unix_env
vifm_src := $(filter-out %/desktop.c %/media_menu.c %/mntent.c %_nix.c, \
$(vifm_src))
endif
ifndef win_env
vifm_src := $(filter-out %/wcwidth.c %/volumes_menu.c %_win.c, $(vifm_src))
endif
vifm_obj := $(B)../src/./tags.o $(vifm_src:%.c=$(B)%.o)
tests_lib := $(BUILD)libtest-support.a
tests_lib_src := $(wildcard test-support/*.c)
tests_lib_obj := $(patsubst %.c,$(BUILD)%.o,$(tests_lib_src))
# make sure that there is one compile_info.c object file in the list
vifm_obj := $(filter-out %/compile_info.o, $(vifm_obj))
vifm_obj += $(B)../src/compile_info.o
ifdef unix_env
make_args := -C $(B)../src/
endif
ifdef win_env
make_args := -C $(B)../src/ -f $(abspath ../src/Makefile.win)
exe_suffix := .exe
endif
CC = $(CROSS)gcc
AR = $(CROSS)ar
# handling of verbosity (non-verbose by default)
ifdef VERBOSE
V = 1
else
V = 0
endif
ACTUAL_CC := $(CC)
ACTUAL_AR := $(AR)
CC_0 = @echo "Compiling $@..."; $(ACTUAL_CC)
CC_1 = $(ACTUAL_CC)
AR_0 = @echo "Archiving $@..."; $(ACTUAL_AR)
AR_1 = $(ACTUAL_AR)
LD_0 = @echo "Linking $@..."; $(ACTUAL_CC)
LD_1 = $(ACTUAL_CC)
AT_0 = @
AT_1 =
# redefine commands according to verbosity state
override CC = $(CC_$(V))
override AR = $(AR_$(V))
override LD = $(LD_$(V))
AT = $(AT_$(V))
# setup compile and link flags (partially depends on OS)
override CFLAGS := $(TESTS_CFLAGS) -MMD -MP -pipe \
-Wall -Wno-char-subscripts \
-Itest-support/ -Itest-support/stic/ \
-include $(B)../build-aux/config.h \
-DTEST
override LDFLAGS := $(TESTS_LDFLAGS)
ifdef unix_env
MF := $(abspath $(B)../src/Makefile)
ifneq ($(wildcard $(MF)),)
override LDFLAGS += \
$(shell grep -m1 'LIBS =' $(MF) | sed 's/^[^=]*=//') \
$(shell grep -m1 'LDFLAGS =' $(MF) | sed 's/^[^=]*=//')
override CFLAGS += \
$(shell grep -m1 'CPPFLAGS =' $(MF) | sed 's/^[^=]*=//') \
$(shell grep -m1 'TESTS_CFLAGS =' $(MF) | sed 's/^[^=]*=//') \
$(shell grep -m1 'SANITIZERS_CFLAGS =' $(MF) | sed 's/^[^=]*=//')
endif
override CFLAGS += -I/usr/include/ncursesw
export UBSAN_OPTIONS := halt_on_error=1
endif
ifdef win_env
override CFLAGS += -pthread
override LDFLAGS += \
$(shell sed -n '/LIBS :=/{s/^[^=]\+=//p;q}' ../src/Makefile.win)
# this part is in conditional of ../src/Makefile.win
ifeq ($(OS),Windows_NT)
override LDFLAGS += -lpdcurses
else
override LDFLAGS += -lcurses
endif
endif
override CFLAGS += -fcommon
ifeq (,$(findstring -lpthread,$(LDFLAGS)))
override LDFLAGS += -pthread
endif
# work around clang
ifeq (,$(findstring clang,$(shell $(ACTUAL_CC) --version)))
ifneq (,$(findstring --coverage, $(LDFLAGS)))
# clang is inconvenient with regard to this flag, don't do coverage with
# it
override CFLAGS += --coverage
override LDFLAGS += --coverage
endif
# don't precompile header with clang (on OS X gcc is likely to be a symlink
# to clang) because it handles macros in a different way
GCH_DEP := $(BUILD)test-support/stic/stic.h.gch
# this flag seems to be gcc-specific and clang freaks out on it with -Werror
override CFLAGS += -Wno-format-truncation
endif
ifdef DEBUG
override CFLAGS += -g -O0
override LDFLAGS += -g
ifdef unix_env
override LDFLAGS += -rdynamic
else
override CFLAGS += -gdwarf-3
endif
ifeq ($(DEBUG),gdb)
TEST_RUN_PREFIX := gdb -q --args
endif
ifeq ($(DEBUG),rr)
TEST_RUN_PREFIX := rr record
endif
ifeq ($(DEBUG),valgrind)
TEST_RUN_PREFIX := valgrind --track-origins=yes --leak-check=full \
--log-file=valgrind-report --error-exitcode=5 \
--suppressions=$(abspath .)/../src/.valgrind.supp
TEST_RUN_POST := || (e=$$$$?; if [ $$$$e -eq 5 ]; then \
cat valgrind-report; \
fi; \
exit $$$$e)
endif
endif
.PHONY: check build clean $(suites) $(apps) appsources
# check and build targets are defined mostly in suite_template
check: build
@if [ "$$(find "$(SANDBOX_PATH)" -mindepth 2 | wc -l)" -ne 0 ]; then \
echo "ERROR: sandbox isn't empty"; \
find $(SANDBOX_PATH) -mindepth 2; \
false; \
fi
clean:
$(RM) -r $(B)bin/ $(SANDBOX_PATH)/
# disable implicit rules to prevent compiling main sources here
.SUFFIXES:
# sources target groups dependencies to avoid invoking nested make per target
$(vifm_obj) ../src/./tags.c: appsources
@# this receipt is needed to make Make recognize that targets were updated
appsources: $(vifm_src)
$(MAKE) $(make_args) vifm$(exe_suffix)
$(BUILD)test-support/%.o: test-support/%.c | $(BUILD)test-support
$(CC) -c -o $@ $(CFLAGS) $<
$(BUILD)test-support/stic/stic.o: test-support/stic/stic.c \
| $(BUILD)test-support/stic
$(CC) -c -o $@ $(CFLAGS) $<
$(BUILD)test-support/stic/stic.h.gch: test-support/stic/stic.h \
| $(BUILD)test-support/stic
$(CC) -c -o $@ $(CFLAGS) $<
$(tests_lib): $(BUILD)test-support/stic/stic.o $(tests_lib_obj) \
| $(BUILD)
$(AR) cr $@ $^
$(BUILD) $(B)bin/$(BINSUBDIR) $(BUILD)test-support $(BUILD)test-support/stic:
$(AT)mkdir -p $@
# this function of two arguments (array and element) returns index of the
# element in the array
pos = $(strip $(eval T := ) \
$(eval i := 0) \
$(foreach elem, $1, \
$(if $(filter $2,$(elem)), \
$(eval i := $(words $T)), \
$(eval T := $T $(elem)))) \
$i)
ifeq (,$(findstring wine,$(TEST_RUN_PREFIX)))
ifeq ($B,)
SANDBOX_PATH := $(abspath .)/sandbox
else
SANDBOX_PATH := $(B)sandbox
endif
TEST_DATA_PATH := $(abspath .)/test-data
else
SANDBOX_PATH := sandbox
TEST_DATA_PATH := test-data
endif
ifneq ($(shell find "$(SANDBOX_PATH)" -mindepth 2 2> /dev/null | wc -l),0)
$(shell $(RM) -r $(SANDBOX_PATH))
endif
# suite definition template, takes single argument: name of the suite
define suite_template
$1.src := $$(sort $$(wildcard $1/*.c))
$1.obj := $$($1.src:%.c=$(BUILD)%.o)
$1.bin := $(B)bin/$(BINSUBDIR)$1$(exe_suffix)
$1.fixtures := $$(subst /,.,\
$$(patsubst %.c,%,$$(filter-out %/suite.c,$$($1.src))))
deps += $$($1.obj:.o=.d)
$$($1.bin): $$($1.obj) $(vifm_obj) $(tests_lib) | $(B)bin/$(BINSUBDIR)
$$(LD) -o $$@ $$^ $(LDFLAGS)
$(BUILD)$1/%.o: $1/%.c $(GCH_DEP) $(BUILD)$1/filelist \
| $(BUILD)$1 $(SANDBOX_PATH)/$1
$$(CC) -c -o $$@ $(CFLAGS) -include test-support/stic/stic.h \
-DTESTID=$$(call pos, $$($1.obj), $$@) \
-DMAXTESTID=$$(words $$($1.obj)) $$< \
-DSUITE_NAME="$1" \
-DTEST_DATA_PATH='"$(TEST_DATA_PATH)"' \
-DSANDBOX_PATH='"$(SANDBOX_PATH)/$1"' \
$(BUILD)$1/filelist: $1/. | $(BUILD)$1
@if [ ! -f "$$@" -o "$$$$(cat $$@ 2> /dev/null)" != '$$($1.src)' ]; then \
echo -n '$$($1.src)' > $$@; \
fi
$(BUILD)$1:
$(AT)mkdir -p $$@
$(SANDBOX_PATH)/$1:
ifeq ($(SANDBOX_PATH),sandbox)
$(AT)mkdir -p $(B)$$@
else
$(AT)mkdir -p $$@
endif
$1: $$($1.bin)
ifeq ($B,)
@$(TEST_RUN_PREFIX) $$< -s $(TEST_RUN_POST)
else
@cd $B && $(TEST_RUN_PREFIX) $$< -s $(TEST_RUN_POST)
endif
# this runs separate fixtures, targets are of the form dir.name
.PHONY: $$($1.fixtures)
$$($1.fixtures): $$($1.bin)
ifeq ($B,)
@$(TEST_RUN_PREFIX) $$^ -s -f $$(subst .,/,$$@).c $(TEST_RUN_POST)
else
@cd $B && $(TEST_RUN_PREFIX) $$^ -s -f $$(subst .,/,$$@).c $(TEST_RUN_POST)
endif
build: $$($1.bin)
# don't add apps to the list of things to run automatically
ifeq (,$(filter $1,$(apps)))
check: $1
endif
endef
# walk throw list of suites+apps and instantiate template for each one
$(foreach suite, $(suites) $(apps), $(eval $(call suite_template,$(suite))))
# extra dependencies between test fixtures
misc: | $(regs_shmem_app.bin)
lua: | $(io_tester_app.bin)
# import dependencies calculated by the compiler
include $(wildcard $(deps) \
$(BUILD)test-support/stic/stic.h.d \
$(BUILD)test-support/*.d)
|