-
Notifications
You must be signed in to change notification settings - Fork 543
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
300 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
load("@rules_python//python:defs.bzl", "py_test") | ||
|
||
py_test( | ||
name = "runfiles_test", | ||
srcs = ["runfiles_test.py"], | ||
deps = ["//python/runfiles"], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,293 @@ | ||
# pylint: disable=g-bad-file-header | ||
# Copyright 2018 The Bazel Authors. All rights reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import os | ||
import tempfile | ||
import unittest | ||
|
||
from python.runfiles import runfiles | ||
|
||
|
||
class RunfilesTest(unittest.TestCase): | ||
# """Unit tests for `runfiles.Runfiles`.""" | ||
|
||
def testRlocationArgumentValidation(self): | ||
r = runfiles.Create({"RUNFILES_DIR": "whatever"}) | ||
self.assertRaises(ValueError, lambda: r.Rlocation(None)) | ||
self.assertRaises(ValueError, lambda: r.Rlocation("")) | ||
self.assertRaises(TypeError, lambda: r.Rlocation(1)) | ||
self.assertRaisesRegex(ValueError, "is not normalized", | ||
lambda: r.Rlocation("../foo")) | ||
self.assertRaisesRegex(ValueError, "is not normalized", | ||
lambda: r.Rlocation("foo/..")) | ||
self.assertRaisesRegex(ValueError, "is not normalized", | ||
lambda: r.Rlocation("foo/../bar")) | ||
self.assertRaisesRegex(ValueError, "is not normalized", | ||
lambda: r.Rlocation("./foo")) | ||
self.assertRaisesRegex(ValueError, "is not normalized", | ||
lambda: r.Rlocation("foo/.")) | ||
self.assertRaisesRegex(ValueError, "is not normalized", | ||
lambda: r.Rlocation("foo/./bar")) | ||
self.assertRaisesRegex(ValueError, "is not normalized", | ||
lambda: r.Rlocation("//foobar")) | ||
self.assertRaisesRegex(ValueError, "is not normalized", | ||
lambda: r.Rlocation("foo//")) | ||
self.assertRaisesRegex(ValueError, "is not normalized", | ||
lambda: r.Rlocation("foo//bar")) | ||
self.assertRaisesRegex(ValueError, "is absolute without a drive letter", | ||
lambda: r.Rlocation("\\foo")) | ||
|
||
def testCreatesManifestBasedRunfiles(self): | ||
with _MockFile(contents=["a/b c/d"]) as mf: | ||
r = runfiles.Create({ | ||
"RUNFILES_MANIFEST_FILE": mf.Path(), | ||
"RUNFILES_DIR": "ignored when RUNFILES_MANIFEST_FILE has a value", | ||
"TEST_SRCDIR": "always ignored", | ||
}) | ||
self.assertEqual(r.Rlocation("a/b"), "c/d") | ||
self.assertIsNone(r.Rlocation("foo")) | ||
|
||
def testManifestBasedRunfilesEnvVars(self): | ||
with _MockFile(name="MANIFEST") as mf: | ||
r = runfiles.Create({ | ||
"RUNFILES_MANIFEST_FILE": mf.Path(), | ||
"TEST_SRCDIR": "always ignored", | ||
}) | ||
self.assertDictEqual( | ||
r.EnvVars(), { | ||
"RUNFILES_MANIFEST_FILE": mf.Path(), | ||
"RUNFILES_DIR": mf.Path()[:-len("/MANIFEST")], | ||
"JAVA_RUNFILES": mf.Path()[:-len("/MANIFEST")], | ||
}) | ||
|
||
with _MockFile(name="foo.runfiles_manifest") as mf: | ||
r = runfiles.Create({ | ||
"RUNFILES_MANIFEST_FILE": mf.Path(), | ||
"TEST_SRCDIR": "always ignored", | ||
}) | ||
self.assertDictEqual( | ||
r.EnvVars(), { | ||
"RUNFILES_MANIFEST_FILE": | ||
mf.Path(), | ||
"RUNFILES_DIR": ( | ||
mf.Path()[:-len("foo.runfiles_manifest")] + "foo.runfiles"), | ||
"JAVA_RUNFILES": ( | ||
mf.Path()[:-len("foo.runfiles_manifest")] + "foo.runfiles"), | ||
}) | ||
|
||
with _MockFile(name="x_manifest") as mf: | ||
r = runfiles.Create({ | ||
"RUNFILES_MANIFEST_FILE": mf.Path(), | ||
"TEST_SRCDIR": "always ignored", | ||
}) | ||
self.assertDictEqual( | ||
r.EnvVars(), { | ||
"RUNFILES_MANIFEST_FILE": mf.Path(), | ||
"RUNFILES_DIR": "", | ||
"JAVA_RUNFILES": "", | ||
}) | ||
|
||
def testCreatesDirectoryBasedRunfiles(self): | ||
r = runfiles.Create({ | ||
"RUNFILES_DIR": "runfiles/dir", | ||
"TEST_SRCDIR": "always ignored", | ||
}) | ||
self.assertEqual(r.Rlocation("a/b"), "runfiles/dir/a/b") | ||
self.assertEqual(r.Rlocation("foo"), "runfiles/dir/foo") | ||
|
||
def testDirectoryBasedRunfilesEnvVars(self): | ||
r = runfiles.Create({ | ||
"RUNFILES_DIR": "runfiles/dir", | ||
"TEST_SRCDIR": "always ignored", | ||
}) | ||
self.assertDictEqual(r.EnvVars(), { | ||
"RUNFILES_DIR": "runfiles/dir", | ||
"JAVA_RUNFILES": "runfiles/dir", | ||
}) | ||
|
||
def testFailsToCreateManifestBasedBecauseManifestDoesNotExist(self): | ||
|
||
def _Run(): | ||
runfiles.Create({"RUNFILES_MANIFEST_FILE": "non-existing path"}) | ||
|
||
self.assertRaisesRegex(IOError, "non-existing path", _Run) | ||
|
||
def testFailsToCreateAnyRunfilesBecauseEnvvarsAreNotDefined(self): | ||
with _MockFile(contents=["a b"]) as mf: | ||
runfiles.Create({ | ||
"RUNFILES_MANIFEST_FILE": mf.Path(), | ||
"RUNFILES_DIR": "whatever", | ||
"TEST_SRCDIR": "always ignored", | ||
}) | ||
runfiles.Create({ | ||
"RUNFILES_DIR": "whatever", | ||
"TEST_SRCDIR": "always ignored", | ||
}) | ||
self.assertIsNone(runfiles.Create({"TEST_SRCDIR": "always ignored"})) | ||
self.assertIsNone(runfiles.Create({"FOO": "bar"})) | ||
|
||
def testManifestBasedRlocation(self): | ||
with _MockFile(contents=[ | ||
"Foo/runfile1", | ||
"Foo/runfile2 C:/Actual Path\\runfile2", | ||
"Foo/Bar/runfile3 D:\\the path\\run file 3.txt", | ||
"Foo/Bar/Dir E:\\Actual Path\\Directory", | ||
]) as mf: | ||
r = runfiles.CreateManifestBased(mf.Path()) | ||
self.assertEqual(r.Rlocation("Foo/runfile1"), "Foo/runfile1") | ||
self.assertEqual(r.Rlocation("Foo/runfile2"), "C:/Actual Path\\runfile2") | ||
self.assertEqual( | ||
r.Rlocation("Foo/Bar/runfile3"), "D:\\the path\\run file 3.txt") | ||
self.assertEqual( | ||
r.Rlocation("Foo/Bar/Dir/runfile4"), | ||
"E:\\Actual Path\\Directory/runfile4") | ||
self.assertEqual( | ||
r.Rlocation("Foo/Bar/Dir/Deeply/Nested/runfile4"), | ||
"E:\\Actual Path\\Directory/Deeply/Nested/runfile4") | ||
self.assertIsNone(r.Rlocation("unknown")) | ||
if RunfilesTest.IsWindows(): | ||
self.assertEqual(r.Rlocation("c:/foo"), "c:/foo") | ||
self.assertEqual(r.Rlocation("c:\\foo"), "c:\\foo") | ||
else: | ||
self.assertEqual(r.Rlocation("/foo"), "/foo") | ||
|
||
def testDirectoryBasedRlocation(self): | ||
# The _DirectoryBased strategy simply joins the runfiles directory and the | ||
# runfile's path on a "/". This strategy does not perform any normalization, | ||
# nor does it check that the path exists. | ||
r = runfiles.CreateDirectoryBased("foo/bar baz//qux/") | ||
self.assertEqual(r.Rlocation("arg"), "foo/bar baz//qux/arg") | ||
if RunfilesTest.IsWindows(): | ||
self.assertEqual(r.Rlocation("c:/foo"), "c:/foo") | ||
self.assertEqual(r.Rlocation("c:\\foo"), "c:\\foo") | ||
else: | ||
self.assertEqual(r.Rlocation("/foo"), "/foo") | ||
|
||
def testPathsFromEnvvars(self): | ||
# Both envvars have a valid value. | ||
mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", | ||
lambda path: path == "mock1/MANIFEST", | ||
lambda path: path == "mock2") | ||
self.assertEqual(mf, "mock1/MANIFEST") | ||
self.assertEqual(dr, "mock2") | ||
|
||
# RUNFILES_MANIFEST_FILE is invalid but RUNFILES_DIR is good and there's a | ||
# runfiles manifest in the runfiles directory. | ||
mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", | ||
lambda path: path == "mock2/MANIFEST", | ||
lambda path: path == "mock2") | ||
self.assertEqual(mf, "mock2/MANIFEST") | ||
self.assertEqual(dr, "mock2") | ||
|
||
# RUNFILES_MANIFEST_FILE is invalid but RUNFILES_DIR is good, but there's no | ||
# runfiles manifest in the runfiles directory. | ||
mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", | ||
lambda path: False, | ||
lambda path: path == "mock2") | ||
self.assertEqual(mf, "") | ||
self.assertEqual(dr, "mock2") | ||
|
||
# RUNFILES_DIR is invalid but RUNFILES_MANIFEST_FILE is good, and it is in | ||
# a valid-looking runfiles directory. | ||
mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", | ||
lambda path: path == "mock1/MANIFEST", | ||
lambda path: path == "mock1") | ||
self.assertEqual(mf, "mock1/MANIFEST") | ||
self.assertEqual(dr, "mock1") | ||
|
||
# RUNFILES_DIR is invalid but RUNFILES_MANIFEST_FILE is good, but it is not | ||
# in any valid-looking runfiles directory. | ||
mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", | ||
lambda path: path == "mock1/MANIFEST", | ||
lambda path: False) | ||
self.assertEqual(mf, "mock1/MANIFEST") | ||
self.assertEqual(dr, "") | ||
|
||
# Both envvars are invalid, but there's a manifest in a runfiles directory | ||
# next to argv0, however there's no other content in the runfiles directory. | ||
mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", | ||
lambda path: path == "argv0.runfiles/MANIFEST", | ||
lambda path: False) | ||
self.assertEqual(mf, "argv0.runfiles/MANIFEST") | ||
self.assertEqual(dr, "") | ||
|
||
# Both envvars are invalid, but there's a manifest next to argv0. There's | ||
# no runfiles tree anywhere. | ||
mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", | ||
lambda path: path == "argv0.runfiles_manifest", | ||
lambda path: False) | ||
self.assertEqual(mf, "argv0.runfiles_manifest") | ||
self.assertEqual(dr, "") | ||
|
||
# Both envvars are invalid, but there's a valid manifest next to argv0, and | ||
# a valid runfiles directory (without a manifest in it). | ||
mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", | ||
lambda path: path == "argv0.runfiles_manifest", | ||
lambda path: path == "argv0.runfiles") | ||
self.assertEqual(mf, "argv0.runfiles_manifest") | ||
self.assertEqual(dr, "argv0.runfiles") | ||
|
||
# Both envvars are invalid, but there's a valid runfiles directory next to | ||
# argv0, though no manifest in it. | ||
mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", | ||
lambda path: False, | ||
lambda path: path == "argv0.runfiles") | ||
self.assertEqual(mf, "") | ||
self.assertEqual(dr, "argv0.runfiles") | ||
|
||
# Both envvars are invalid, but there's a valid runfiles directory next to | ||
# argv0 with a valid manifest in it. | ||
mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", | ||
lambda path: path == "argv0.runfiles/MANIFEST", | ||
lambda path: path == "argv0.runfiles") | ||
self.assertEqual(mf, "argv0.runfiles/MANIFEST") | ||
self.assertEqual(dr, "argv0.runfiles") | ||
|
||
# Both envvars are invalid and there's no runfiles directory or manifest | ||
# next to the argv0. | ||
mf, dr = runfiles._PathsFrom("argv0", "mock1/MANIFEST", "mock2", | ||
lambda path: False, lambda path: False) | ||
self.assertEqual(mf, "") | ||
self.assertEqual(dr, "") | ||
|
||
@staticmethod | ||
def IsWindows(): | ||
return os.name == "nt" | ||
|
||
|
||
class _MockFile(object): | ||
|
||
def __init__(self, name=None, contents=None): | ||
self._contents = contents or [] | ||
self._name = name or "x" | ||
self._path = None | ||
|
||
def __enter__(self): | ||
tmpdir = os.environ.get("TEST_TMPDIR") | ||
self._path = os.path.join(tempfile.mkdtemp(dir=tmpdir), self._name) | ||
with open(self._path, "wt") as f: | ||
f.writelines(l + "\n" for l in self._contents) | ||
return self | ||
|
||
def __exit__(self, exc_type, exc_value, traceback): | ||
os.remove(self._path) | ||
os.rmdir(os.path.dirname(self._path)) | ||
|
||
def Path(self): | ||
return self._path | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |