From: Junio C Hamano Date: Wed, 17 Feb 2016 18:13:28 +0000 (-0800) Subject: Merge branch 'js/mingw-tests' X-Git-Tag: v2.8.0-rc0~54 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/4b589e5b28af077ddbdd5b72b6217c7447d45cb5?hp=-c Merge branch 'js/mingw-tests' Test scripts have been updated to remove assumptions that are not portable between Git for POSIX and Git for Windows, or to skip ones with expectations that are not satisfiable on Git for Windows. * js/mingw-tests: (21 commits) gitignore: ignore generated test-fake-ssh executable mingw: do not bother to test funny file names mingw: skip a test in t9130 that cannot pass on Windows mingw: handle the missing POSIXPERM prereq in t9124 mingw: avoid illegal filename in t9118 mingw: mark t9100's test cases with appropriate prereqs t0008: avoid absolute path mingw: work around pwd issues in the tests mingw: fix t9700's assumption about directory separators mingw: skip test in t1508 that fails due to path conversion tests: turn off git-daemon tests if FIFOs are not available mingw: disable mkfifo-based tests mingw: accomodate t0060-path-utils for MSYS2 mingw: fix t5601-clone.sh mingw: let lstat() fail with errno == ENOTDIR when appropriate mingw: try to delete target directory before renaming mingw: prepare the TMPDIR environment variable for shell scripts mingw: factor out Windows specific environment setup Git.pm: stop assuming that absolute paths start with a slash mingw: do not trust MSYS2's MinGW gettext.sh ... --- 4b589e5b28af077ddbdd5b72b6217c7447d45cb5 diff --combined Makefile index fc2f1ab2c3,8000492146..10566d6481 --- a/Makefile +++ b/Makefile @@@ -583,6 -583,7 +583,7 @@@ TEST_PROGRAMS_NEED_X += test-delt TEST_PROGRAMS_NEED_X += test-dump-cache-tree TEST_PROGRAMS_NEED_X += test-dump-split-index TEST_PROGRAMS_NEED_X += test-dump-untracked-cache + TEST_PROGRAMS_NEED_X += test-fake-ssh TEST_PROGRAMS_NEED_X += test-genrandom TEST_PROGRAMS_NEED_X += test-hashmap TEST_PROGRAMS_NEED_X += test-index-version @@@ -2025,7 -2026,6 +2026,7 @@@ $(VCSSVN_LIB): $(VCSSVN_OBJS export DEFAULT_EDITOR DEFAULT_PAGER +.PHONY: doc man html info pdf doc: $(MAKE) -C Documentation all @@@ -2069,7 -2069,6 +2070,7 @@@ po/git.pot: $(GENERATED_H) FORC $(LOCALIZED_PERL) mv $@+ $@ +.PHONY: pot pot: po/git.pot POFILES := $(wildcard po/*.po) @@@ -2279,7 -2278,6 +2280,7 @@@ mergetools_instdir_SQ = $(subst ','\'', install_bindir_programs := $(patsubst %,%$X,$(BINDIR_PROGRAMS_NEED_X)) $(BINDIR_PROGRAMS_NO_X) +.PHONY: profile-install profile-fast-install profile-install: profile $(MAKE) install @@@ -2346,8 -2344,6 +2347,8 @@@ endi done && \ ./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X" +.PHONY: install-gitweb install-doc install-man install-html install-info install-pdf +.PHONY: quick-install-doc quick-install-man quick-install-html install-gitweb: $(MAKE) -C gitweb install @@@ -2407,7 -2403,6 +2408,7 @@@ rpm: dis htmldocs = git-htmldocs-$(GIT_VERSION) manpages = git-manpages-$(GIT_VERSION) +.PHONY: dist-doc distclean dist-doc: $(RM) -r .doc-tmp-dir mkdir .doc-tmp-dir @@@ -2476,8 -2471,6 +2477,8 @@@ ALL_COMMANDS += gi ALL_COMMANDS += gitk ALL_COMMANDS += gitweb ALL_COMMANDS += git-gui git-citool + +.PHONY: check-docs check-docs:: @(for v in $(ALL_COMMANDS); \ do \ @@@ -2522,7 -2515,6 +2523,7 @@@ check-builtins: ### Test suite coverage testing # .PHONY: coverage coverage-clean coverage-compile coverage-test coverage-report +.PHONY: coverage-untested-functions cover_db cover_db_html .PHONY: coverage-clean-results coverage: diff --combined compat/mingw.c index 77a51d3f72,545e952a58..fbe69b874b --- a/compat/mingw.c +++ b/compat/mingw.c @@@ -454,6 -454,39 +454,39 @@@ static inline time_t filetime_to_time_t return (time_t)(filetime_to_hnsec(ft) / 10000000); } + /** + * Verifies that safe_create_leading_directories() would succeed. + */ + static int has_valid_directory_prefix(wchar_t *wfilename) + { + int n = wcslen(wfilename); + + while (n > 0) { + wchar_t c = wfilename[--n]; + DWORD attributes; + + if (!is_dir_sep(c)) + continue; + + wfilename[n] = L'\0'; + attributes = GetFileAttributesW(wfilename); + wfilename[n] = c; + if (attributes == FILE_ATTRIBUTE_DIRECTORY || + attributes == FILE_ATTRIBUTE_DEVICE) + return 1; + if (attributes == INVALID_FILE_ATTRIBUTES) + switch (GetLastError()) { + case ERROR_PATH_NOT_FOUND: + continue; + case ERROR_FILE_NOT_FOUND: + /* This implies parent directory exists. */ + return 1; + } + return 0; + } + return 1; + } + /* We keep the do_lstat code in a separate function to avoid recursion. * When a path ends with a slash, the stat will fail with ENOENT. In * this case, we strip the trailing slashes and stat again. @@@ -514,6 -547,12 +547,12 @@@ static int do_lstat(int follow, const c case ERROR_NOT_ENOUGH_MEMORY: errno = ENOMEM; break; + case ERROR_PATH_NOT_FOUND: + if (!has_valid_directory_prefix(wfilename)) { + errno = ENOTDIR; + break; + } + /* fallthru */ default: errno = ENOENT; break; @@@ -1603,7 -1642,12 +1642,12 @@@ repeat if (gle == ERROR_ACCESS_DENIED && (attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) { if (attrs & FILE_ATTRIBUTE_DIRECTORY) { - errno = EISDIR; + DWORD attrsold = GetFileAttributesW(wpold); + if (attrsold == INVALID_FILE_ATTRIBUTES || + !(attrsold & FILE_ATTRIBUTE_DIRECTORY)) + errno = EISDIR; + else if (!_wrmdir(wpnew)) + goto repeat; return -1; } if ((attrs & FILE_ATTRIBUTE_READONLY) && @@@ -1935,31 -1979,28 +1979,31 @@@ pid_t waitpid(pid_t pid, int *status, i return -1; } +int mingw_skip_dos_drive_prefix(char **path) +{ + int ret = has_dos_drive_prefix(*path); + *path += ret; + return ret; +} + int mingw_offset_1st_component(const char *path) { - int offset = 0; - if (has_dos_drive_prefix(path)) - offset = 2; + char *pos = (char *)path; /* unc paths */ - else if (is_dir_sep(path[0]) && is_dir_sep(path[1])) { - + if (!skip_dos_drive_prefix(&pos) && + is_dir_sep(pos[0]) && is_dir_sep(pos[1])) { /* skip server name */ - char *pos = strpbrk(path + 2, "\\/"); + pos = strpbrk(pos + 2, "\\/"); if (!pos) return 0; /* Error: malformed unc path */ do { pos++; } while (*pos && !is_dir_sep(*pos)); - - offset = pos - path; } - return offset + is_dir_sep(path[offset]); + return pos + is_dir_sep(*pos) - path; } int xutftowcsn(wchar_t *wcs, const char *utfs, size_t wcslen, int utflen) @@@ -2047,6 -2088,37 +2091,37 @@@ int xwcstoutf(char *utf, const wchar_t return -1; } + static void setup_windows_environment() + { + char *tmp = getenv("TMPDIR"); + + /* on Windows it is TMP and TEMP */ + if (!tmp) { + if (!(tmp = getenv("TMP"))) + tmp = getenv("TEMP"); + if (tmp) { + setenv("TMPDIR", tmp, 1); + tmp = getenv("TMPDIR"); + } + } + + if (tmp) { + /* + * Convert all dir separators to forward slashes, + * to help shell commands called from the Git + * executable (by not mistaking the dir separators + * for escape characters). + */ + for (; *tmp; tmp++) + if (*tmp == '\\') + *tmp = '/'; + } + + /* simulate TERM to enable auto-color (see color.c) */ + if (!getenv("TERM")) + setenv("TERM", "cygwin", 1); + } + /* * Disable MSVCRT command line wildcard expansion (__getmainargs called from * mingw startup code, see init.c in mingw runtime). @@@ -2125,19 -2197,7 +2200,7 @@@ void mingw_startup( qsort(environ, i, sizeof(char*), compareenv); /* fix Windows specific environment settings */ - - /* on Windows it is TMP and TEMP */ - if (!mingw_getenv("TMPDIR")) { - const char *tmp = mingw_getenv("TMP"); - if (!tmp) - tmp = mingw_getenv("TEMP"); - if (tmp) - setenv("TMPDIR", tmp, 1); - } - - /* simulate TERM to enable auto-color (see color.c) */ - if (!getenv("TERM")) - setenv("TERM", "cygwin", 1); + setup_windows_environment(); /* initialize critical section for waitpid pinfo_t list */ InitializeCriticalSection(&pinfo_cs); diff --combined t/t0060-path-utils.sh index f0152a7ab4,602b08b141..8532a028e7 --- a/t/t0060-path-utils.sh +++ b/t/t0060-path-utils.sh @@@ -36,12 -36,21 +36,21 @@@ if test $rootoff = 2; the rootoff= # we are on Unix else rootoff=$(($rootoff-1)) + # In MSYS2, the root directory "/" is translated into a Windows + # directory *with* trailing slash. Let's test for that and adjust + # our expected longest ancestor length accordingly. + case "$(test-path-utils print_path /)" in + */) rootslash=1;; + *) rootslash=0;; + esac fi ancestor() { # We do some math with the expected ancestor length. expected=$3 if test -n "$rootoff" && test "x$expected" != x-1; then + expected=$(($expected-$rootslash)) + test $expected -lt 0 || expected=$(($expected+$rootoff)) fi test_expect_success "longest ancestor: $1 $2 => $expected" \ @@@ -59,9 -68,6 +68,9 @@@ case $(uname -s) i ;; esac +test_expect_success basename 'test-path-utils basename' +test_expect_success dirname 'test-path-utils dirname' + norm_path "" "" norm_path . "" norm_path ./ "" diff --combined t/t3600-rm.sh index 2e47a2bfd8,11e7526488..d046d98aec --- a/t/t3600-rm.sh +++ b/t/t3600-rm.sh @@@ -14,7 -14,7 +14,7 @@@ test_expect_success git add -- foo bar baz 'space embedded' -q && git commit -m 'add normal files'" - if touch -- 'tab embedded' 'newline + if test_have_prereq !MINGW && touch -- 'tab embedded' 'newline embedded' 2>/dev/null then test_set_prereq FUNNYNAMES @@@ -115,7 -115,7 +115,7 @@@ test_expect_success '"rm" command print git add test-file && git commit -m "add file for rm test" && git rm test-file > rm-output && - test `grep "^rm " rm-output | wc -l` = 1 && + test $(grep "^rm " rm-output | wc -l) = 1 && rm -f test-file rm-output && git commit -m "remove file from rm test" ' @@@ -125,7 -125,7 +125,7 @@@ test_expect_success '"rm" command suppr git add test-file && git commit -m "add file for rm --quiet test" && git rm --quiet test-file > rm-output && - test `wc -l < rm-output` = 0 && + test $(wc -l < rm-output) = 0 && rm -f test-file rm-output && git commit -m "remove file from rm --quiet test" ' diff --combined t/t5601-clone.sh index 669ec9ba81,e40fc2673f..c1efb8e445 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@@ -4,6 -4,9 +4,9 @@@ test_description=clon . ./test-lib.sh + X= + test_have_prereq !MINGW || X=.exe + test_expect_success setup ' rm -fr .git && @@@ -65,29 -68,6 +68,29 @@@ test_expect_success 'clone respects GIT ' +test_expect_success 'clone from hooks' ' + + test_create_repo r0 && + cd r0 && + test_commit initial && + cd .. && + git init r1 && + cd r1 && + cat >.git/hooks/pre-commit <<-\EOF && + #!/bin/sh + git clone ../r0 ../r2 + exit 1 + EOF + chmod u+x .git/hooks/pre-commit && + : >file && + git add file && + test_must_fail git commit -m invoke-hook && + cd .. && + test_cmp r0/.git/HEAD r2/.git/HEAD && + test_cmp r0/initial.t r2/initial.t + +' + test_expect_success 'clone creates intermediate directories' ' git clone src long/path/to/dst && @@@ -244,7 -224,7 +247,7 @@@ test_expect_success 'clone separate git ' test_expect_success 'clone separate gitdir: output' ' - echo "gitdir: `pwd`/realgitdir" >expected && + echo "gitdir: $(pwd)/realgitdir" >expected && test_cmp expected dst/.git ' @@@ -305,14 -285,9 +308,9 @@@ test_expect_success 'clone checking ou setup_ssh_wrapper () { test_expect_success 'setup ssh wrapper' ' - write_script "$TRASH_DIRECTORY/ssh-wrapper" <<-\EOF && - echo >>"$TRASH_DIRECTORY/ssh-output" "ssh: $*" && - # throw away all but the last argument, which should be the - # command - while test $# -gt 1; do shift; done - eval "$1" - EOF - GIT_SSH="$TRASH_DIRECTORY/ssh-wrapper" && + cp "$GIT_BUILD_DIR/test-fake-ssh$X" \ + "$TRASH_DIRECTORY/ssh-wrapper$X" && + GIT_SSH="$TRASH_DIRECTORY/ssh-wrapper$X" && export GIT_SSH && export TRASH_DIRECTORY && >"$TRASH_DIRECTORY"/ssh-output @@@ -320,8 -295,8 +318,8 @@@ } copy_ssh_wrapper_as () { - cp "$TRASH_DIRECTORY/ssh-wrapper" "$1" && - GIT_SSH="$1" && + cp "$TRASH_DIRECTORY/ssh-wrapper$X" "${1%$X}$X" && + GIT_SSH="${1%$X}$X" && export GIT_SSH } diff --combined t/t9100-git-svn-basic.sh index 258d9b8cef,5464b5bd14..56acc1e70e --- a/t/t9100-git-svn-basic.sh +++ b/t/t9100-git-svn-basic.sh @@@ -30,8 -30,7 +30,7 @@@ test_expect_success echo "deep dir" >dir/a/b/c/d/e/file && mkdir bar && echo "zzz" >bar/zzz && - echo "#!/bin/sh" >exec.sh && - chmod +x exec.sh && + write_script exec.sh /dev/null ) && rm -rf import && @@@ -117,7 -116,7 +116,7 @@@ test_expect_success "$name" name='remove executable bit from a file' - test_expect_success "$name" ' + test_expect_success POSIXPERM "$name" ' rm -f "$GIT_DIR"/index && git checkout -f -b mybranch5 ${remotes_git_svn} && chmod -x exec.sh && @@@ -130,7 -129,7 +129,7 @@@ name='add executable bit back file' - test_expect_success "$name" ' + test_expect_success POSIXPERM "$name" ' chmod +x exec.sh && git update-index exec.sh && git commit -m "$name" && @@@ -141,7 -140,7 +140,7 @@@ name='executable file becomes a symlink to file' - test_expect_success "$name" ' + test_expect_success SYMLINKS "$name" ' rm exec.sh && ln -s file exec.sh && git update-index exec.sh && @@@ -153,7 -152,7 +152,7 @@@ name='new symlink is added to a file that was also just made executable' - test_expect_success "$name" ' + test_expect_success POSIXPERM,SYMLINKS "$name" ' chmod +x file && ln -s file exec-2.sh && git update-index --add file exec-2.sh && @@@ -165,7 -164,7 +164,7 @@@ test -h "$SVN_TREE"/exec-2.sh' name='modify a symlink to become a file' - test_expect_success "$name" ' + test_expect_success POSIXPERM,SYMLINKS "$name" ' echo git help >help && rm exec-2.sh && cp help exec-2.sh && @@@ -181,7 -180,8 +180,8 @@@ name="commit with UTF-8 message: locale: $GIT_SVN_LC_ALL" LC_ALL="$GIT_SVN_LC_ALL" export LC_ALL - test_expect_success UTF8 "$name" " + # This test relies on the previous test, hence requires POSIXPERM,SYMLINKS + test_expect_success UTF8,POSIXPERM,SYMLINKS "$name" " echo '# hello' >> exec-2.sh && git update-index exec-2.sh && git commit -m 'éï∏' && @@@ -214,7 -214,7 +214,7 @@@ tree d667270a1f7b109f5eb3aaea21ede14b56 tree 8f51f74cf0163afc9ad68a4b1537288c4558b5a4 EOF - test_expect_success "$name" "test_cmp a expected" + test_expect_success POSIXPERM,SYMLINKS "$name" "test_cmp a expected" test_expect_success 'exit if remote refs are ambigious' " git config --add svn-remote.svn.fetch \ @@@ -265,18 -265,18 +265,18 @@@ test_expect_success 'able to dcommit t git update-index --add d && git commit -m '/bar/d should be in the log' && git svn dcommit -i bar && - test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" && + test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\" && mkdir newdir && echo new > newdir/dir && git update-index --add newdir/dir && git commit -m 'add a new directory' && git svn dcommit -i bar && - test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" && + test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\" && echo foo >> newdir/dir && git update-index newdir/dir && git commit -m 'modify a file in new directory' && git svn dcommit -i bar && - test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" + test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\" " test_expect_success 'dcommit should not fail with a touched file' ' @@@ -295,7 -295,7 +295,7 @@@ test_expect_success 'able to set-tree t git update-index d && git commit -m 'update /bar/d' && git svn set-tree -i bar HEAD && - test -z \"\`git diff refs/heads/my-bar refs/remotes/bar\`\" + test -z \"\$(git diff refs/heads/my-bar refs/remotes/bar)\" " test_expect_success 'git-svn works in a bare repository' ' diff --combined t/t9118-git-svn-funky-branch-names.sh index a2219154b8,5c9c0f87d3..ecb1fed147 --- a/t/t9118-git-svn-funky-branch-names.sh +++ b/t/t9118-git-svn-funky-branch-names.sh @@@ -23,8 -23,11 +23,11 @@@ test_expect_success 'setup svnrepo' "$svnrepo/pr ject/branches/$scary_uri" && svn_cmd cp -m "leading dot" "$svnrepo/pr ject/trunk" \ "$svnrepo/pr ject/branches/.leading_dot" && - svn_cmd cp -m "trailing dot" "$svnrepo/pr ject/trunk" \ - "$svnrepo/pr ject/branches/trailing_dot." && + if test_have_prereq !MINGW + then + svn_cmd cp -m "trailing dot" "$svnrepo/pr ject/trunk" \ + "$svnrepo/pr ject/branches/trailing_dot." + fi && svn_cmd cp -m "trailing .lock" "$svnrepo/pr ject/trunk" \ "$svnrepo/pr ject/branches/trailing_dotlock.lock" && svn_cmd cp -m "reflog" "$svnrepo/pr ject/trunk" \ @@@ -35,7 -38,7 +38,7 @@@ # SVN 1.7 will truncate "not-a%40{0]" to just "not-a". # Look at what SVN wound up naming the branch and use that. # Be sure to escape the @ if it shows up. -non_reflog=`svn_cmd ls "$svnrepo/pr ject/branches" | grep not-a | sed 's/\///' | sed 's/@/%40/'` +non_reflog=$(svn_cmd ls "$svnrepo/pr ject/branches" | grep not-a | sed 's/\///' | sed 's/@/%40/') test_expect_success 'test clone with funky branch names' ' git svn clone -s "$svnrepo/pr ject" project && @@@ -45,7 -48,10 +48,10 @@@ git rev-parse "refs/remotes/origin/more%20fun%20plugin!" && git rev-parse "refs/remotes/origin/$scary_ref" && git rev-parse "refs/remotes/origin/%2Eleading_dot" && - git rev-parse "refs/remotes/origin/trailing_dot%2E" && + if test_have_prereq !MINGW + then + git rev-parse "refs/remotes/origin/trailing_dot%2E" + fi && git rev-parse "refs/remotes/origin/trailing_dotlock%2Elock" && git rev-parse "refs/remotes/origin/$non_reflog" ) diff --combined t/t9130-git-svn-authors-file.sh index d306b77c31,0a9cd87136..41264818cc --- a/t/t9130-git-svn-authors-file.sh +++ b/t/t9130-git-svn-authors-file.sh @@@ -26,7 -26,7 +26,7 @@@ test_expect_success 'start import with test_expect_success 'imported 2 revisions successfully' ' ( cd x - test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 2 && + test "$(git rev-list refs/remotes/git-svn | wc -l)" -eq 2 && git rev-list -1 --pretty=raw refs/remotes/git-svn | \ grep "^author BBBBBBB BBBBBBB " && git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \ @@@ -43,7 -43,7 +43,7 @@@ test_expect_success 'continues to impor ( cd x git svn fetch --authors-file=../svn-authors && - test "`git rev-list refs/remotes/git-svn | wc -l`" -eq 4 && + test "$(git rev-list refs/remotes/git-svn | wc -l)" -eq 4 && git rev-list -1 --pretty=raw refs/remotes/git-svn | \ grep "^author DDDDDDD DDDDDDD " && git rev-list -1 --pretty=raw refs/remotes/git-svn~1 | \ @@@ -73,8 -73,8 +73,8 @@@ tmp_config_get () test_expect_success 'failure happened without negative side effects' ' ( cd aa-work && - test 6 -eq "`tmp_config_get svn-remote.svn.branches-maxRev`" && - test 6 -eq "`tmp_config_get svn-remote.svn.tags-maxRev`" + test 6 -eq "$(tmp_config_get svn-remote.svn.branches-maxRev)" && + test 6 -eq "$(tmp_config_get svn-remote.svn.tags-maxRev)" ) ' @@@ -86,12 -86,12 +86,12 @@@ test_expect_success 'fetch continues af ( cd aa-work && git svn fetch --authors-file=../svn-authors && - test 8 -eq "`tmp_config_get svn-remote.svn.branches-maxRev`" && - test 8 -eq "`tmp_config_get svn-remote.svn.tags-maxRev`" + test 8 -eq "$(tmp_config_get svn-remote.svn.branches-maxRev)" && + test 8 -eq "$(tmp_config_get svn-remote.svn.tags-maxRev)" ) ' - test_expect_success 'fresh clone with svn.authors-file in config' ' + test_expect_success !MINGW 'fresh clone with svn.authors-file in config' ' ( rm -r "$GIT_DIR" && test x = x"$(git config svn.authorsfile)" && diff --combined t/test-lib.sh index 51e4a88c33,32ac1a6936..0b47eb6bb2 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@@ -907,11 -907,9 +907,11 @@@ yes () y="$*" fi - while echo "$y" + i=0 + while test $i -lt 99 do - : + echo "$y" + i=$(($i+1)) done } @@@ -1000,7 -998,7 +1000,7 @@@ test_i18ngrep () test_lazy_prereq PIPE ' # test whether the filesystem supports FIFOs case $(uname -s) in - CYGWIN*) + CYGWIN*|MINGW*) false ;; *) @@@ -1056,28 -1054,20 +1056,28 @@@ test_lazy_prereq NOT_ROOT test "$uid" != 0 ' -# On a filesystem that lacks SANITY, a file can be deleted even if -# the containing directory doesn't have write permissions, or a file -# can be accessed even if the containing directory doesn't have read -# or execute permissions, causing our tests that validate that Git -# works sensibly in such situations. +# SANITY is about "can you correctly predict what the filesystem would +# do by only looking at the permission bits of the files and +# directories?" A typical example of !SANITY is running the test +# suite as root, where a test may expect "chmod -r file && cat file" +# to fail because file is supposed to be unreadable after a successful +# chmod. In an environment (i.e. combination of what filesystem is +# being used and who is running the tests) that lacks SANITY, you may +# be able to delete or create a file when the containing directory +# doesn't have write permissions, or access a file even if the +# containing directory doesn't have read or execute permissions. + test_lazy_prereq SANITY ' mkdir SANETESTD.1 SANETESTD.2 && chmod +w SANETESTD.1 SANETESTD.2 && >SANETESTD.1/x 2>SANETESTD.2/x && chmod -w SANETESTD.1 && + chmod -r SANETESTD.1/x && chmod -rx SANETESTD.2 || error "bug in test sript: cannot prepare SANETESTD" + ! test -r SANETESTD.1/x && ! rm SANETESTD.1/x && ! test -f SANETESTD.2/x status=$?