mirror of
https://github.com/qpdf/qpdf.git
synced 2025-01-03 15:17:29 +00:00
Add automated test for shell wildcard expansion
Wildcard expansion is different in Windows from non-Windows and sometimes requires special link options to work. Add tests that fail if we link incorrectly.
This commit is contained in:
parent
cfafac8d13
commit
deeface146
1
.github/workflows/main.yml
vendored
1
.github/workflows/main.yml
vendored
@ -41,7 +41,6 @@ jobs:
|
||||
name: distribution
|
||||
path: distribution
|
||||
Windows:
|
||||
# If updating this, see note in TODO about MSVC wildcard expansion.
|
||||
runs-on: windows-2019
|
||||
needs: Distfiles
|
||||
strategy:
|
||||
|
34
TODO
34
TODO
@ -4,8 +4,7 @@ Candidates for upcoming release
|
||||
* Easy build/test
|
||||
* #460: potential malware in fuzzer seed corpus
|
||||
* Consider building workflow on a schedule to detect build rot. This
|
||||
may enable safe use of *-latest especially if Windows wildcard is
|
||||
testable.
|
||||
should enable safe use of *-latest on runners.
|
||||
|
||||
* Fuzz crashes
|
||||
* See "New" below
|
||||
@ -29,9 +28,6 @@ Candidates for upcoming release
|
||||
because of changes in the build environment, library dependencies,
|
||||
compiler upgrades, etc.
|
||||
|
||||
* Find a way to deal with MSVC wildcard expansion, even if it requires
|
||||
creating a separate step or adding code to build-windows.bat.
|
||||
|
||||
* See if we can work in Windows Build/External Libraries (below)
|
||||
|
||||
* Remember to check work `qpdf` project for private issues
|
||||
@ -220,34 +216,6 @@ Page splitting/merging
|
||||
|
||||
* Form fields: should be similar to outlines.
|
||||
|
||||
MSVC Wildcard Expansion
|
||||
=======================
|
||||
|
||||
(This section is referenced in azure_pipelines.yml and
|
||||
.github/workflows/main.yml.)
|
||||
|
||||
The qpdf executable built with msvc is linked with setargv.obj or
|
||||
wsetargv.obj so that wildcard expansion works. It doesn't work exactly
|
||||
the way a UNIX system would work in that the program itself does the
|
||||
expansion (rather than the shell), which means that invoking qpdf.exe
|
||||
as built by msvc will expand "*.pdf" just as it will expand *.pdf. In
|
||||
some earlier versions, wildcard expansion didn't work with the msvc
|
||||
executable. The way to make this work appears to be different in some
|
||||
versions of MSVC than in others. As such, if upgrading MSVC or
|
||||
changing the build environment, the wildcard expansion behavior of the
|
||||
qpdf executable in Windows should be retested manually.
|
||||
|
||||
Unfortunately, there is no automated test for wildcard expansion with
|
||||
MSVC because I can't figure out how to prevent qtest from expanding
|
||||
the wildcards before passing them in, and explicitly running "cmd /c
|
||||
..." from qtest doesn't seem to work in Azure Pipelines (haven't
|
||||
attempted in GitHub Actions), though I can make it work locally.
|
||||
|
||||
Ideally, we should figure out a way to test this in CI by having a
|
||||
test that fails if wildcard expansion is broken. In the absence of
|
||||
this, it will be necessary to test the behavior manually in both mingw
|
||||
and msvc when run from cmd and from msys bash.
|
||||
|
||||
Performance
|
||||
===========
|
||||
|
||||
|
@ -8,6 +8,7 @@ BINS_qpdf = \
|
||||
test_pdf_doc_encoding \
|
||||
test_pdf_unicode \
|
||||
test_renumber \
|
||||
test_shell_glob \
|
||||
test_tokenizer \
|
||||
test_unicode_filenames \
|
||||
test_xref
|
||||
@ -23,15 +24,14 @@ TC_SRCS_qpdf = $(wildcard libqpdf/*.cc) $(wildcard qpdf/*.cc)
|
||||
|
||||
# -----
|
||||
|
||||
XCXXFLAGS_qpdf_qpdf := $(WINDOWS_WMAIN_COMPILE)
|
||||
XLDFLAGS_qpdf_qpdf := $(WINDOWS_WMAIN_LINK)
|
||||
XLINK_FLAGS_qpdf_qpdf := $(WINDOWS_WMAIN_XLINK_FLAGS)
|
||||
XCXXFLAGS_qpdf_test_unicode_filenames := $(WINDOWS_WMAIN_COMPILE)
|
||||
XLDFLAGS_qpdf_test_unicode_filenames := $(WINDOWS_WMAIN_LINK)
|
||||
XLINK_FLAGS_qpdf_test_unicode_filenames := $(WINDOWS_WMAIN_XLINK_FLAGS)
|
||||
XCXXFLAGS_qpdf_fix-qdf := $(WINDOWS_WMAIN_COMPILE)
|
||||
XLDFLAGS_qpdf_fix-qdf := $(WINDOWS_WMAIN_LINK)
|
||||
XLINK_FLAGS_qpdf_fix-qdf := $(WINDOWS_WMAIN_XLINK_FLAGS)
|
||||
define use_wmain
|
||||
XCXXFLAGS_qpdf_$(1) := $(WINDOWS_WMAIN_COMPILE)
|
||||
XLDFLAGS_qpdf_$(1) := $(WINDOWS_WMAIN_LINK)
|
||||
XLINK_FLAGS_qpdf_$(1) := $(WINDOWS_WMAIN_XLINK_FLAGS)
|
||||
endef
|
||||
|
||||
$(foreach B,qpdf test_unicode_filenames fix-qdf test_shell_glob,\
|
||||
$(eval $(call use_wmain,$(B))))
|
||||
|
||||
$(foreach B,$(BINS_qpdf),$(eval \
|
||||
OBJS_$(B) = $(call src_to_obj,qpdf/$(B).cc)))
|
||||
|
@ -189,6 +189,17 @@ foreach my $d (['auto-ü', 1], ['auto-öπ', 2])
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
}
|
||||
|
||||
show_ntests();
|
||||
# ----------
|
||||
$td->notify("--- Windows shell globbing ---");
|
||||
|
||||
$td->runtest("shell wildcard expansion",
|
||||
{$td->COMMAND => "test_shell_glob 'good*.pdf'"},
|
||||
{$td->STRING => "PASSED\n", $td->EXIT_STATUS => 0},
|
||||
$td->NORMALIZE_NEWLINES);
|
||||
|
||||
$n_tests += 1;
|
||||
|
||||
show_ntests();
|
||||
# ----------
|
||||
$td->notify("--- Replace Input ---");
|
||||
|
64
qpdf/test_shell_glob.cc
Normal file
64
qpdf/test_shell_glob.cc
Normal file
@ -0,0 +1,64 @@
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <qpdf/QUtil.hh>
|
||||
|
||||
int realmain(int argc, char* argv[])
|
||||
{
|
||||
// In Windows, shell globbing is handled by the runtime, so
|
||||
// passing '*' as argument results in wildcard expansion. In
|
||||
// non-Windows, globbing is done by the shell, so passing '*'
|
||||
// shows up as '*'. In Windows with MSVC, it is necessary to link
|
||||
// a certain way for this to work. To test this, we invoke this
|
||||
// program with a single quoted argument containing a shell glob
|
||||
// expression. In Windows, we expect to see multiple arguments,
|
||||
// none of which contain '*'. Otherwise, we expected to see the
|
||||
// exact glob string that was passed in. The effectiveness of this
|
||||
// test was exercised by manually breaking the link options for
|
||||
// msvc and seeing that the test fails under that condition.
|
||||
|
||||
bool found_star = false;
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
if (strchr(argv[i], '*') != nullptr)
|
||||
{
|
||||
found_star = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef _WIN32
|
||||
bool passed = ((! found_star) && (argc > 2));
|
||||
#else
|
||||
bool passed = (found_star && (argc == 2));
|
||||
#endif
|
||||
if (passed)
|
||||
{
|
||||
std::cout << "PASSED" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "FAILED" << std::endl;
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
std::cout << argv[i] << std::endl;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef WINDOWS_WMAIN
|
||||
|
||||
extern "C"
|
||||
int wmain(int argc, wchar_t* argv[])
|
||||
{
|
||||
return QUtil::call_main_from_wmain(argc, argv, realmain);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
return realmain(argc, argv);
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user