Reformat .bzl files with buildifier and add format check.

Buildifier 0.12.0 includes initial support for reformatting .bzl files.
- Reformat all the bzl files.
- Expand the travis check to check the .bzl files also.
This commit is contained in:
Thomas Van Lenten 2018-06-12 13:09:57 -04:00
parent a5431b7bab
commit e5203c0f5d
26 changed files with 1727 additions and 1770 deletions

View File

@ -26,9 +26,14 @@ fi
# Asked to do a buildifier run.
if [[ -n "${BUILDIFER:-}" ]]; then
# bazelbuild/buildtools/issues/220 - diff doesn't include the file that needs updating
if ! find . -name BUILD -print | xargs buildifier -d > /dev/null 2>&1 ; then
echo "ERROR: BUILD file formatting issue(s)"
find . -name BUILD -print -exec buildifier -v -d {} \;
if ! find . \( -name BUILD -o -name "*.bzl" \) -print | xargs buildifier -d > /dev/null 2>&1 ; then
echo "ERROR: BUILD/.bzl file formatting issue(s):"
echo ""
find . \( -name BUILD -o -name "*.bzl" \) -print -exec buildifier -v -d {} \;
echo ""
echo "Please download the latest buildifier"
echo " https://github.com/bazelbuild/buildtools/releases"
echo "and run it over the changed BUILD/.bzl files."
exit 1
fi
fi

25
lib.bzl
View File

@ -14,22 +14,21 @@
"""Index from which multiple modules can be loaded."""
load("//lib:collections.bzl", _collections="collections")
load("//lib:dicts.bzl", _dicts="dicts")
load("//lib:new_sets.bzl", _new_sets="sets")
load("//lib:partial.bzl", _partial="partial")
load("//lib:paths.bzl", _paths="paths")
load("//lib:selects.bzl", _selects="selects")
load("//lib:sets.bzl", _sets="sets")
load("//lib:shell.bzl", _shell="shell")
load("//lib:structs.bzl", _structs="structs")
load("//lib:types.bzl", _types="types")
load("//lib:versions.bzl", _versions="versions")
load("//lib:collections.bzl", _collections = "collections")
load("//lib:dicts.bzl", _dicts = "dicts")
load("//lib:new_sets.bzl", _new_sets = "sets")
load("//lib:partial.bzl", _partial = "partial")
load("//lib:paths.bzl", _paths = "paths")
load("//lib:selects.bzl", _selects = "selects")
load("//lib:sets.bzl", _sets = "sets")
load("//lib:shell.bzl", _shell = "shell")
load("//lib:structs.bzl", _structs = "structs")
load("//lib:types.bzl", _types = "types")
load("//lib:versions.bzl", _versions = "versions")
# The unittest module is treated differently to give more convenient names to
# the assert functions, while keeping them in the same .bzl file.
load("//lib:unittest.bzl", _asserts="asserts", _unittest="unittest")
load("//lib:unittest.bzl", _asserts = "asserts", _unittest = "unittest")
collections = _collections
dicts = _dicts

View File

@ -14,60 +14,56 @@
"""Skylib module containing functions that operate on collections."""
def _after_each(separator, iterable):
"""Inserts `separator` after each item in `iterable`.
"""Inserts `separator` after each item in `iterable`.
Args:
separator: The value to insert after each item in `iterable`.
iterable: The list into which to intersperse the separator.
Args:
separator: The value to insert after each item in `iterable`.
iterable: The list into which to intersperse the separator.
Returns:
A new list with `separator` after each item in `iterable`.
"""
result = []
for x in iterable:
result.append(x)
result.append(separator)
return result
Returns:
A new list with `separator` after each item in `iterable`.
"""
result = []
for x in iterable:
result.append(x)
result.append(separator)
return result
def _before_each(separator, iterable):
"""Inserts `separator` before each item in `iterable`.
"""Inserts `separator` before each item in `iterable`.
Args:
separator: The value to insert before each item in `iterable`.
iterable: The list into which to intersperse the separator.
Args:
separator: The value to insert before each item in `iterable`.
iterable: The list into which to intersperse the separator.
Returns:
A new list with `separator` before each item in `iterable`.
"""
result = []
for x in iterable:
result.append(separator)
result.append(x)
return result
Returns:
A new list with `separator` before each item in `iterable`.
"""
result = []
for x in iterable:
result.append(separator)
result.append(x)
return result
def _uniq(iterable):
"""Returns a list of unique elements in `iterable`.
"""Returns a list of unique elements in `iterable`.
Requires all the elements to be hashable.
Requires all the elements to be hashable.
Args:
iterable: An iterable to filter.
Returns:
A new list with all unique elements from `iterable`.
"""
unique_elements = {element: None for element in iterable}
return unique_elements.keys()
Args:
iterable: An iterable to filter.
Returns:
A new list with all unique elements from `iterable`.
"""
unique_elements = {element: None for element in iterable}
return unique_elements.keys()
collections = struct(
after_each=_after_each,
before_each=_before_each,
uniq=_uniq,
after_each = _after_each,
before_each = _before_each,
uniq = _uniq,
)

View File

@ -14,30 +14,28 @@
"""Skylib module containing functions that operate on dictionaries."""
def _add(*dictionaries):
"""Returns a new `dict` that has all the entries of the given dictionaries.
"""Returns a new `dict` that has all the entries of the given dictionaries.
If the same key is present in more than one of the input dictionaries, the
last of them in the argument list overrides any earlier ones.
If the same key is present in more than one of the input dictionaries, the
last of them in the argument list overrides any earlier ones.
This function is designed to take zero or one arguments as well as multiple
dictionaries, so that it follows arithmetic identities and callers can avoid
special cases for their inputs: the sum of zero dictionaries is the empty
dictionary, and the sum of a single dictionary is a copy of itself.
This function is designed to take zero or one arguments as well as multiple
dictionaries, so that it follows arithmetic identities and callers can avoid
special cases for their inputs: the sum of zero dictionaries is the empty
dictionary, and the sum of a single dictionary is a copy of itself.
Args:
*dictionaries: Zero or more dictionaries to be added.
Returns:
A new `dict` that has all the entries of the given dictionaries.
"""
result = {}
for d in dictionaries:
result.update(d)
return result
Args:
*dictionaries: Zero or more dictionaries to be added.
Returns:
A new `dict` that has all the entries of the given dictionaries.
"""
result = {}
for d in dictionaries:
result.update(d)
return result
dicts = struct(
add=_add,
add = _add,
)

View File

@ -22,230 +22,215 @@
load(":dicts.bzl", "dicts")
def _make(elements = None):
"""Creates a new set.
def _make(elements=None):
"""Creates a new set.
All elements must be hashable.
All elements must be hashable.
Args:
elements: Optional sequence to construct the set out of.
Returns:
A set containing the passed in values.
"""
elements = elements if elements else []
return struct(_values = {e: None for e in elements})
Args:
elements: Optional sequence to construct the set out of.
Returns:
A set containing the passed in values.
"""
elements = elements if elements else []
return struct(_values = {e: None for e in elements})
def _copy(s):
"""Creates a new set from another set.
"""Creates a new set from another set.
Args:
s: A set, as returned by `sets.make()`.
Returns:
A new set containing the same elements as `s`.
"""
return struct(_values = dict(s._values))
Args:
s: A set, as returned by `sets.make()`.
Returns:
A new set containing the same elements as `s`.
"""
return struct(_values = dict(s._values))
def _to_list(s):
"""Creates a list from the values in the set.
"""Creates a list from the values in the set.
Args:
s: A set, as returned by `sets.make()`.
Returns:
A list of values inserted into the set.
"""
return s._values.keys()
Args:
s: A set, as returned by `sets.make()`.
Returns:
A list of values inserted into the set.
"""
return s._values.keys()
def _insert(s, e):
"""Inserts an element into the set.
"""Inserts an element into the set.
Element must be hashable. This mutates the orginal set.
Element must be hashable. This mutates the orginal set.
Args:
s: A set, as returned by `sets.make()`.
e: The element to be inserted.
Returns:
The set `s` with `e` included.
"""
s._values[e] = None
return s
Args:
s: A set, as returned by `sets.make()`.
e: The element to be inserted.
Returns:
The set `s` with `e` included.
"""
s._values[e] = None
return s
def _remove(s, e):
"""Removes an element from the set.
"""Removes an element from the set.
Element must be hashable. This mutates the orginal set.
Element must be hashable. This mutates the orginal set.
Args:
s: A set, as returned by `sets.make()`.
e: The element to be removed.
Returns:
The set `s` with `e` removed.
"""
s._values.pop(e)
return s
Args:
s: A set, as returned by `sets.make()`.
e: The element to be removed.
Returns:
The set `s` with `e` removed.
"""
s._values.pop(e)
return s
def _contains(a, e):
"""Checks for the existence of an element in a set.
"""Checks for the existence of an element in a set.
Args:
a: A set, as returned by `sets.make()`.
e: The element to look for.
Returns:
True if the element exists in the set, False if the element does not.
"""
return e in a._values
Args:
a: A set, as returned by `sets.make()`.
e: The element to look for.
Returns:
True if the element exists in the set, False if the element does not.
"""
return e in a._values
def _get_shorter_and_longer(a, b):
"""Returns two sets in the order of shortest and longest.
"""Returns two sets in the order of shortest and longest.
Args:
a: A set, as returned by `sets.make()`.
b: A set, as returned by `sets.make()`.
Returns:
`a`, `b` if `a` is shorter than `b` - or `b`, `a` if `b` is shorter than `a`.
"""
if _length(a) < _length(b):
return a, b
return b, a
Args:
a: A set, as returned by `sets.make()`.
b: A set, as returned by `sets.make()`.
Returns:
`a`, `b` if `a` is shorter than `b` - or `b`, `a` if `b` is shorter than `a`.
"""
if _length(a) < _length(b):
return a, b
return b, a
def _is_equal(a, b):
"""Returns whether two sets are equal.
"""Returns whether two sets are equal.
Args:
a: A set, as returned by `sets.make()`.
b: A set, as returned by `sets.make()`.
Returns:
True if `a` is equal to `b`, False otherwise.
"""
return a._values == b._values
Args:
a: A set, as returned by `sets.make()`.
b: A set, as returned by `sets.make()`.
Returns:
True if `a` is equal to `b`, False otherwise.
"""
return a._values == b._values
def _is_subset(a, b):
"""Returns whether `a` is a subset of `b`.
"""Returns whether `a` is a subset of `b`.
Args:
a: A set, as returned by `sets.make()`.
b: A set, as returned by `sets.make()`.
Returns:
True if `a` is a subset of `b`, False otherwise.
"""
for e in a._values.keys():
if e not in b._values:
return False
return True
Args:
a: A set, as returned by `sets.make()`.
b: A set, as returned by `sets.make()`.
Returns:
True if `a` is a subset of `b`, False otherwise.
"""
for e in a._values.keys():
if e not in b._values:
return False
return True
def _disjoint(a, b):
"""Returns whether two sets are disjoint.
"""Returns whether two sets are disjoint.
Two sets are disjoint if they have no elements in common.
Two sets are disjoint if they have no elements in common.
Args:
a: A set, as returned by `sets.make()`.
b: A set, as returned by `sets.make()`.
Returns:
True if `a` and `b` are disjoint, False otherwise.
"""
shorter, longer = _get_shorter_and_longer(a, b)
for e in shorter._values.keys():
if e in longer._values:
return False
return True
Args:
a: A set, as returned by `sets.make()`.
b: A set, as returned by `sets.make()`.
Returns:
True if `a` and `b` are disjoint, False otherwise.
"""
shorter, longer = _get_shorter_and_longer(a, b)
for e in shorter._values.keys():
if e in longer._values:
return False
return True
def _intersection(a, b):
"""Returns the intersection of two sets.
"""Returns the intersection of two sets.
Args:
a: A set, as returned by `sets.make()`.
b: A set, as returned by `sets.make()`.
Returns:
A set containing the elements that are in both `a` and `b`.
"""
shorter, longer = _get_shorter_and_longer(a, b)
return struct(_values = {e: None for e in shorter._values.keys() if e in longer._values})
Args:
a: A set, as returned by `sets.make()`.
b: A set, as returned by `sets.make()`.
Returns:
A set containing the elements that are in both `a` and `b`.
"""
shorter, longer = _get_shorter_and_longer(a, b)
return struct(_values = {e: None for e in shorter._values.keys() if e in longer._values})
def _union(*args):
"""Returns the union of several sets.
"""Returns the union of several sets.
Args:
*args: An arbitrary number of sets or lists.
Returns:
The set union of all sets or lists in `*args`.
"""
return struct(_values = dicts.add(*[s._values for s in args]))
Args:
*args: An arbitrary number of sets or lists.
Returns:
The set union of all sets or lists in `*args`.
"""
return struct(_values = dicts.add(*[s._values for s in args]))
def _difference(a, b):
"""Returns the elements in `a` that are not in `b`.
"""Returns the elements in `a` that are not in `b`.
Args:
a: A set, as returned by `sets.make()`.
b: A set, as returned by `sets.make()`.
Returns:
A set containing the elements that are in `a` but not in `b`.
"""
return struct(_values = {e: None for e in a._values.keys() if e not in b._values})
Args:
a: A set, as returned by `sets.make()`.
b: A set, as returned by `sets.make()`.
Returns:
A set containing the elements that are in `a` but not in `b`.
"""
return struct(_values = {e: None for e in a._values.keys() if e not in b._values})
def _length(s):
"""Returns the number of elements in a set.
"""Returns the number of elements in a set.
Args:
s: A set, as returned by `sets.make()`.
Args:
s: A set, as returned by `sets.make()`.
Returns:
An integer representing the number of elements in the set.
"""
return len(s._values)
Returns:
An integer representing the number of elements in the set.
"""
return len(s._values)
def _repr(s):
"""Returns a string value representing the set.
"""Returns a string value representing the set.
Args:
s: A set, as returned by `sets.make()`.
Returns:
A string representing the set.
"""
return repr(s._values.keys())
Args:
s: A set, as returned by `sets.make()`.
Returns:
A string representing the set.
"""
return repr(s._values.keys())
sets = struct(
make = _make,
copy = _copy,
to_list = _to_list,
insert = _insert,
contains = _contains,
is_equal = _is_equal,
is_subset = _is_subset,
disjoint = _disjoint,
intersection = _intersection,
union = _union,
difference = _difference,
length = _length,
remove = _remove,
repr = _repr,
str = _repr,
make = _make,
copy = _copy,
to_list = _to_list,
insert = _insert,
contains = _contains,
is_equal = _is_equal,
is_subset = _is_subset,
disjoint = _disjoint,
intersection = _intersection,
union = _union,
difference = _difference,
length = _length,
remove = _remove,
repr = _repr,
str = _repr,
)

View File

@ -20,111 +20,111 @@ Similar to https://docs.python.org/3/library/functools.html#functools.partial.
"""
def _call(partial, *args, **kwargs):
"""Calls a partial created using `make`.
"""Calls a partial created using `make`.
Args:
partial: The partial to be called.
*args: Additional positional arguments to be appended to the ones given to
make.
**kwargs: Additional keyword arguments to augment and override the ones
given to make.
Args:
partial: The partial to be called.
*args: Additional positional arguments to be appended to the ones given to
make.
**kwargs: Additional keyword arguments to augment and override the ones
given to make.
Returns:
Whatever the function in the partial returns.
"""
function_args = partial.args + args
function_kwargs = dict(partial.kwargs)
function_kwargs.update(kwargs)
return partial.function(*function_args, **function_kwargs)
Returns:
Whatever the function in the partial returns.
"""
function_args = partial.args + args
function_kwargs = dict(partial.kwargs)
function_kwargs.update(kwargs)
return partial.function(*function_args, **function_kwargs)
def _make(func, *args, **kwargs):
"""Creates a partial that can be called using `call`.
"""Creates a partial that can be called using `call`.
A partial can have args assigned to it at the make site, and can have args
passed to it at the call sites.
A partial can have args assigned to it at the make site, and can have args
passed to it at the call sites.
A partial 'function' can be defined with positional args and kwargs:
A partial 'function' can be defined with positional args and kwargs:
# function with no args
def function1():
...
# function with no args
def function1():
...
# function with 2 args
def function2(arg1, arg2):
...
# function with 2 args
def function2(arg1, arg2):
...
# function with 2 args and keyword args
def function3(arg1, arg2, x, y):
...
# function with 2 args and keyword args
def function3(arg1, arg2, x, y):
...
The positional args passed to the function are the args passed into make
followed by any additional positional args given to call. The below example
illustrates a function with two positional arguments where one is supplied by
make and the other by call:
The positional args passed to the function are the args passed into make
followed by any additional positional args given to call. The below example
illustrates a function with two positional arguments where one is supplied by
make and the other by call:
# function demonstrating 1 arg at make site, and 1 arg at call site
def _foo(make_arg1, func_arg1):
print(make_arg1 + " " + func_arg1 + "!")
# function demonstrating 1 arg at make site, and 1 arg at call site
def _foo(make_arg1, func_arg1):
print(make_arg1 + " " + func_arg1 + "!")
For example:
For example:
hi_func = partial.make(_foo, "Hello")
bye_func = partial.make(_foo, "Goodbye")
partial.call(hi_func, "Jennifer")
partial.call(hi_func, "Dave")
partial.call(bye_func, "Jennifer")
partial.call(bye_func, "Dave")
hi_func = partial.make(_foo, "Hello")
bye_func = partial.make(_foo, "Goodbye")
partial.call(hi_func, "Jennifer")
partial.call(hi_func, "Dave")
partial.call(bye_func, "Jennifer")
partial.call(bye_func, "Dave")
prints:
prints:
"Hello, Jennifer!"
"Hello, Dave!"
"Goodbye, Jennifer!"
"Goodbye, Dave!"
"Hello, Jennifer!"
"Hello, Dave!"
"Goodbye, Jennifer!"
"Goodbye, Dave!"
The keyword args given to the function are the kwargs passed into make
unioned with the keyword args given to call. In case of a conflict, the
keyword args given to call take precedence. This allows you to set a default
value for keyword arguments and override it at the call site.
The keyword args given to the function are the kwargs passed into make
unioned with the keyword args given to call. In case of a conflict, the
keyword args given to call take precedence. This allows you to set a default
value for keyword arguments and override it at the call site.
Example with a make site arg, a call site arg, a make site kwarg and a
call site kwarg:
Example with a make site arg, a call site arg, a make site kwarg and a
call site kwarg:
def _foo(make_arg1, call_arg1, make_location, call_location):
print(make_arg1 + " is from " + make_location + " and " +
call_arg1 + " is from " + call_location + "!")
def _foo(make_arg1, call_arg1, make_location, call_location):
print(make_arg1 + " is from " + make_location + " and " +
call_arg1 + " is from " + call_location + "!")
func = partial.make(_foo, "Ben", make_location="Hollywood")
partial.call(func, "Jennifer", call_location="Denver")
func = partial.make(_foo, "Ben", make_location="Hollywood")
partial.call(func, "Jennifer", call_location="Denver")
Prints "Ben is from Hollywood and Jennifer is from Denver!".
Prints "Ben is from Hollywood and Jennifer is from Denver!".
partial.call(func, "Jennifer", make_location="LA", call_location="Denver")
partial.call(func, "Jennifer", make_location="LA", call_location="Denver")
Prints "Ben is from LA and Jennifer is from Denver!".
Prints "Ben is from LA and Jennifer is from Denver!".
Note that keyword args may not overlap with positional args, regardless of
whether they are given during the make or call step. For instance, you can't
do:
Note that keyword args may not overlap with positional args, regardless of
whether they are given during the make or call step. For instance, you can't
do:
def foo(x):
pass
def foo(x):
pass
func = partial.make(foo, 1)
partial.call(func, x=2)
func = partial.make(foo, 1)
partial.call(func, x=2)
Args:
func: The function to be called.
*args: Positional arguments to be passed to function.
**kwargs: Keyword arguments to be passed to function. Note that these can
be overridden at the call sites.
Args:
func: The function to be called.
*args: Positional arguments to be passed to function.
**kwargs: Keyword arguments to be passed to function. Note that these can
be overridden at the call sites.
Returns:
A new `partial` that can be called using `call`
"""
return struct(function=func, args=args, kwargs=kwargs)
Returns:
A new `partial` that can be called using `call`
"""
return struct(function = func, args = args, kwargs = kwargs)
partial = struct(
make=_make,
call=_call,
make = _make,
call = _call,
)

View File

@ -19,233 +19,224 @@ path separators (forward slash, "/"); they do not handle Windows-style paths
with backslash separators or drive letters.
"""
def _basename(p):
"""Returns the basename (i.e., the file portion) of a path.
"""Returns the basename (i.e., the file portion) of a path.
Note that if `p` ends with a slash, this function returns an empty string.
This matches the behavior of Python's `os.path.basename`, but differs from
the Unix `basename` command (which would return the path segment preceding
the final slash).
Note that if `p` ends with a slash, this function returns an empty string.
This matches the behavior of Python's `os.path.basename`, but differs from
the Unix `basename` command (which would return the path segment preceding
the final slash).
Args:
p: The path whose basename should be returned.
Returns:
The basename of the path, which includes the extension.
"""
return p.rpartition("/")[-1]
Args:
p: The path whose basename should be returned.
Returns:
The basename of the path, which includes the extension.
"""
return p.rpartition("/")[-1]
def _dirname(p):
"""Returns the dirname of a path.
"""Returns the dirname of a path.
The dirname is the portion of `p` up to but not including the file portion
(i.e., the basename). Any slashes immediately preceding the basename are not
included, unless omitting them would make the dirname empty.
The dirname is the portion of `p` up to but not including the file portion
(i.e., the basename). Any slashes immediately preceding the basename are not
included, unless omitting them would make the dirname empty.
Args:
p: The path whose dirname should be returned.
Returns:
The dirname of the path.
"""
prefix, sep, _ = p.rpartition("/")
if not prefix:
return sep
else:
# If there are multiple consecutive slashes, strip them all out as Python's
# os.path.dirname does.
return prefix.rstrip("/")
Args:
p: The path whose dirname should be returned.
Returns:
The dirname of the path.
"""
prefix, sep, _ = p.rpartition("/")
if not prefix:
return sep
else:
# If there are multiple consecutive slashes, strip them all out as Python's
# os.path.dirname does.
return prefix.rstrip("/")
def _is_absolute(path):
"""Returns `True` if `path` is an absolute path.
"""Returns `True` if `path` is an absolute path.
Args:
path: A path (which is a string).
Returns:
`True` if `path` is an absolute path.
"""
return path.startswith("/") or (len(path)>2 and path[1] == ":")
Args:
path: A path (which is a string).
Returns:
`True` if `path` is an absolute path.
"""
return path.startswith("/") or (len(path) > 2 and path[1] == ":")
def _join(path, *others):
"""Joins one or more path components intelligently.
"""Joins one or more path components intelligently.
This function mimics the behavior of Python's `os.path.join` function on POSIX
platform. It returns the concatenation of `path` and any members of `others`,
inserting directory separators before each component except the first. The
separator is not inserted if the path up until that point is either empty or
already ends in a separator.
This function mimics the behavior of Python's `os.path.join` function on POSIX
platform. It returns the concatenation of `path` and any members of `others`,
inserting directory separators before each component except the first. The
separator is not inserted if the path up until that point is either empty or
already ends in a separator.
If any component is an absolute path, all previous components are discarded.
If any component is an absolute path, all previous components are discarded.
Args:
path: A path segment.
*others: Additional path segments.
Args:
path: A path segment.
*others: Additional path segments.
Returns:
A string containing the joined paths.
"""
result = path
Returns:
A string containing the joined paths.
"""
result = path
for p in others:
if _is_absolute(p):
result = p
elif not result or result.endswith("/"):
result += p
else:
result += "/" + p
return result
for p in others:
if _is_absolute(p):
result = p
elif not result or result.endswith("/"):
result += p
else:
result += "/" + p
return result
def _normalize(path):
"""Normalizes a path, eliminating double slashes and other redundant segments.
"""Normalizes a path, eliminating double slashes and other redundant segments.
This function mimics the behavior of Python's `os.path.normpath` function on
POSIX platforms; specifically:
This function mimics the behavior of Python's `os.path.normpath` function on
POSIX platforms; specifically:
- If the entire path is empty, "." is returned.
- All "." segments are removed, unless the path consists solely of a single
"." segment.
- Trailing slashes are removed, unless the path consists solely of slashes.
- ".." segments are removed as long as there are corresponding segments
earlier in the path to remove; otherwise, they are retained as leading ".."
segments.
- Single and double leading slashes are preserved, but three or more leading
slashes are collapsed into a single leading slash.
- Multiple adjacent internal slashes are collapsed into a single slash.
- If the entire path is empty, "." is returned.
- All "." segments are removed, unless the path consists solely of a single
"." segment.
- Trailing slashes are removed, unless the path consists solely of slashes.
- ".." segments are removed as long as there are corresponding segments
earlier in the path to remove; otherwise, they are retained as leading ".."
segments.
- Single and double leading slashes are preserved, but three or more leading
slashes are collapsed into a single leading slash.
- Multiple adjacent internal slashes are collapsed into a single slash.
Args:
path: A path.
Args:
path: A path.
Returns:
The normalized path.
"""
if not path:
return "."
Returns:
The normalized path.
"""
if not path:
return "."
if path.startswith("//") and not path.startswith("///"):
initial_slashes = 2
elif path.startswith("/"):
initial_slashes = 1
else:
initial_slashes = 0
is_relative = (initial_slashes == 0)
components = path.split("/")
new_components = []
for component in components:
if component in ("", "."):
continue
if component == "..":
if new_components and new_components[-1] != "..":
# Only pop the last segment if it isn't another "..".
new_components.pop()
elif is_relative:
# Preserve leading ".." segments for relative paths.
new_components.append(component)
if path.startswith("//") and not path.startswith("///"):
initial_slashes = 2
elif path.startswith("/"):
initial_slashes = 1
else:
new_components.append(component)
initial_slashes = 0
is_relative = (initial_slashes == 0)
path = "/".join(new_components)
if not is_relative:
path = ("/" * initial_slashes) + path
components = path.split("/")
new_components = []
return path or "."
for component in components:
if component in ("", "."):
continue
if component == "..":
if new_components and new_components[-1] != "..":
# Only pop the last segment if it isn't another "..".
new_components.pop()
elif is_relative:
# Preserve leading ".." segments for relative paths.
new_components.append(component)
else:
new_components.append(component)
path = "/".join(new_components)
if not is_relative:
path = ("/" * initial_slashes) + path
return path or "."
def _relativize(path, start):
"""Returns the portion of `path` that is relative to `start`.
"""Returns the portion of `path` that is relative to `start`.
Because we do not have access to the underlying file system, this
implementation differs slightly from Python's `os.path.relpath` in that it
will fail if `path` is not beneath `start` (rather than use parent segments to
walk up to the common file system root).
Because we do not have access to the underlying file system, this
implementation differs slightly from Python's `os.path.relpath` in that it
will fail if `path` is not beneath `start` (rather than use parent segments to
walk up to the common file system root).
Relativizing paths that start with parent directory references only works if
the path both start with the same initial parent references.
Relativizing paths that start with parent directory references only works if
the path both start with the same initial parent references.
Args:
path: The path to relativize.
start: The ancestor path against which to relativize.
Args:
path: The path to relativize.
start: The ancestor path against which to relativize.
Returns:
The portion of `path` that is relative to `start`.
"""
segments = _normalize(path).split("/")
start_segments = _normalize(start).split("/")
if start_segments == ["."]:
start_segments = []
start_length = len(start_segments)
Returns:
The portion of `path` that is relative to `start`.
"""
segments = _normalize(path).split("/")
start_segments = _normalize(start).split("/")
if start_segments == ["."]:
start_segments = []
start_length = len(start_segments)
if (path.startswith("/") != start.startswith("/") or
len(segments) < start_length):
fail("Path '%s' is not beneath '%s'" % (path, start))
if (path.startswith("/") != start.startswith("/") or
len(segments) < start_length):
fail("Path '%s' is not beneath '%s'" % (path, start))
for ancestor_segment, segment in zip(start_segments, segments):
if ancestor_segment != segment:
fail("Path '%s' is not beneath '%s'" % (path, start))
length = len(segments) - start_length
result_segments = segments[-length:]
return "/".join(result_segments)
for ancestor_segment, segment in zip(start_segments, segments):
if ancestor_segment != segment:
fail("Path '%s' is not beneath '%s'" % (path, start))
length = len(segments) - start_length
result_segments = segments[-length:]
return "/".join(result_segments)
def _replace_extension(p, new_extension):
"""Replaces the extension of the file at the end of a path.
"""Replaces the extension of the file at the end of a path.
If the path has no extension, the new extension is added to it.
If the path has no extension, the new extension is added to it.
Args:
p: The path whose extension should be replaced.
new_extension: The new extension for the file. The new extension should
begin with a dot if you want the new filename to have one.
Returns:
The path with the extension replaced (or added, if it did not have one).
"""
return _split_extension(p)[0] + new_extension
Args:
p: The path whose extension should be replaced.
new_extension: The new extension for the file. The new extension should
begin with a dot if you want the new filename to have one.
Returns:
The path with the extension replaced (or added, if it did not have one).
"""
return _split_extension(p)[0] + new_extension
def _split_extension(p):
"""Splits the path `p` into a tuple containing the root and extension.
"""Splits the path `p` into a tuple containing the root and extension.
Leading periods on the basename are ignored, so
`path.split_extension(".bashrc")` returns `(".bashrc", "")`.
Leading periods on the basename are ignored, so
`path.split_extension(".bashrc")` returns `(".bashrc", "")`.
Args:
p: The path whose root and extension should be split.
Args:
p: The path whose root and extension should be split.
Returns:
A tuple `(root, ext)` such that the root is the path without the file
extension, and `ext` is the file extension (which, if non-empty, contains
the leading dot). The returned tuple always satisfies the relationship
`root + ext == p`.
"""
b = _basename(p)
last_dot_in_basename = b.rfind(".")
Returns:
A tuple `(root, ext)` such that the root is the path without the file
extension, and `ext` is the file extension (which, if non-empty, contains
the leading dot). The returned tuple always satisfies the relationship
`root + ext == p`.
"""
b = _basename(p)
last_dot_in_basename = b.rfind(".")
# If there is no dot or the only dot in the basename is at the front, then
# there is no extension.
if last_dot_in_basename <= 0:
return (p, "")
dot_distance_from_end = len(b) - last_dot_in_basename
return (p[:-dot_distance_from_end], p[-dot_distance_from_end:])
# If there is no dot or the only dot in the basename is at the front, then
# there is no extension.
if last_dot_in_basename <= 0:
return (p, "")
dot_distance_from_end = len(b) - last_dot_in_basename
return (p[:-dot_distance_from_end], p[-dot_distance_from_end:])
paths = struct(
basename=_basename,
dirname=_dirname,
is_absolute=_is_absolute,
join=_join,
normalize=_normalize,
relativize=_relativize,
replace_extension=_replace_extension,
split_extension=_split_extension,
basename = _basename,
dirname = _dirname,
is_absolute = _is_absolute,
join = _join,
normalize = _normalize,
relativize = _relativize,
replace_extension = _replace_extension,
split_extension = _split_extension,
)

View File

@ -14,71 +14,69 @@
"""Skylib module containing convenience interfaces for select()."""
def _with_or(input_dict, no_match_error=''):
"""Drop-in replacement for `select()` that supports ORed keys.
def _with_or(input_dict, no_match_error = ""):
"""Drop-in replacement for `select()` that supports ORed keys.
Args:
input_dict: The same dictionary `select()` takes, except keys may take
either the usual form `"//foo:config1"` or
`("//foo:config1", "//foo:config2", ...)` to signify
`//foo:config1` OR `//foo:config2` OR `...`.
no_match_error: Optional custom error to report if no condition matches.
Args:
input_dict: The same dictionary `select()` takes, except keys may take
either the usual form `"//foo:config1"` or
`("//foo:config1", "//foo:config2", ...)` to signify
`//foo:config1` OR `//foo:config2` OR `...`.
no_match_error: Optional custom error to report if no condition matches.
Example:
Example:
```build
deps = selects.with_or({
"//configs:one": [":dep1"],
("//configs:two", "//configs:three"): [":dep2or3"],
"//configs:four": [":dep4"],
"//conditions:default": [":default"]
})
```
```build
deps = selects.with_or({
"//configs:one": [":dep1"],
("//configs:two", "//configs:three"): [":dep2or3"],
"//configs:four": [":dep4"],
"//conditions:default": [":default"]
})
```
Key labels may appear at most once anywhere in the input.
Key labels may appear at most once anywhere in the input.
Returns:
A native `select()` that expands
Returns:
A native `select()` that expands
`("//configs:two", "//configs:three"): [":dep2or3"]`
`("//configs:two", "//configs:three"): [":dep2or3"]`
to
```build
"//configs:two": [":dep2or3"],
"//configs:three": [":dep2or3"],
```
"""
return select(_with_or_dict(input_dict), no_match_error=no_match_error)
to
```build
"//configs:two": [":dep2or3"],
"//configs:three": [":dep2or3"],
```
"""
return select(_with_or_dict(input_dict), no_match_error = no_match_error)
def _with_or_dict(input_dict):
"""Variation of `with_or` that returns the dict of the `select()`.
"""Variation of `with_or` that returns the dict of the `select()`.
Unlike `select()`, the contents of the dict can be inspected by Skylark
macros.
Unlike `select()`, the contents of the dict can be inspected by Skylark
macros.
Args:
input_dict: Same as `with_or`.
Returns:
A dictionary usable by a native `select()`.
"""
output_dict = {}
for (key, value) in input_dict.items():
if type(key) == type(()):
for config_setting in key:
if config_setting in output_dict.keys():
fail("key %s appears multiple times" % config_setting)
output_dict[config_setting] = value
else:
if key in output_dict.keys():
fail("key %s appears multiple times" % key)
output_dict[key] = value
return output_dict
Args:
input_dict: Same as `with_or`.
Returns:
A dictionary usable by a native `select()`.
"""
output_dict = {}
for (key, value) in input_dict.items():
if type(key) == type(()):
for config_setting in key:
if config_setting in output_dict.keys():
fail("key %s appears multiple times" % config_setting)
output_dict[config_setting] = value
else:
if key in output_dict.keys():
fail("key %s appears multiple times" % key)
output_dict[key] = value
return output_dict
selects = struct(
with_or=_with_or,
with_or_dict=_with_or_dict
with_or = _with_or,
with_or_dict = _with_or_dict,
)

View File

@ -26,113 +26,105 @@ duplicate elements are ignored). Functions that return new sets always return
them as the `set` type, regardless of the types of the inputs.
"""
def _precondition_only_sets_or_lists(*args):
"""Verifies that all arguments are either sets or lists.
"""Verifies that all arguments are either sets or lists.
The build will fail if any of the arguments is neither a set nor a list.
Args:
*args: A list of values that must be sets or lists.
"""
for a in args:
t = type(a)
if t not in("depset", "list"):
fail("Expected arguments to be depset or list, but found type %s: %r" %
(t, a))
The build will fail if any of the arguments is neither a set nor a list.
Args:
*args: A list of values that must be sets or lists.
"""
for a in args:
t = type(a)
if t not in ("depset", "list"):
fail("Expected arguments to be depset or list, but found type %s: %r" %
(t, a))
def _is_equal(a, b):
"""Returns whether two sets are equal.
"""Returns whether two sets are equal.
Args:
a: A depset or a list.
b: A depset or a list.
Returns:
True if `a` is equal to `b`, False otherwise.
"""
_precondition_only_sets_or_lists(a, b)
return sorted(depset(a)) == sorted(depset(b))
Args:
a: A depset or a list.
b: A depset or a list.
Returns:
True if `a` is equal to `b`, False otherwise.
"""
_precondition_only_sets_or_lists(a, b)
return sorted(depset(a)) == sorted(depset(b))
def _is_subset(a, b):
"""Returns whether `a` is a subset of `b`.
"""Returns whether `a` is a subset of `b`.
Args:
a: A depset or a list.
b: A depset or a list.
Returns:
True if `a` is a subset of `b`, False otherwise.
"""
_precondition_only_sets_or_lists(a, b)
for e in a:
if e not in b:
return False
return True
Args:
a: A depset or a list.
b: A depset or a list.
Returns:
True if `a` is a subset of `b`, False otherwise.
"""
_precondition_only_sets_or_lists(a, b)
for e in a:
if e not in b:
return False
return True
def _disjoint(a, b):
"""Returns whether two sets are disjoint.
"""Returns whether two sets are disjoint.
Two sets are disjoint if they have no elements in common.
Two sets are disjoint if they have no elements in common.
Args:
a: A set or list.
b: A set or list.
Returns:
True if `a` and `b` are disjoint, False otherwise.
"""
_precondition_only_sets_or_lists(a, b)
for e in a:
if e in b:
return False
return True
Args:
a: A set or list.
b: A set or list.
Returns:
True if `a` and `b` are disjoint, False otherwise.
"""
_precondition_only_sets_or_lists(a, b)
for e in a:
if e in b:
return False
return True
def _intersection(a, b):
"""Returns the intersection of two sets.
"""Returns the intersection of two sets.
Args:
a: A set or list.
b: A set or list.
Returns:
A set containing the elements that are in both `a` and `b`.
"""
_precondition_only_sets_or_lists(a, b)
return depset([e for e in a if e in b])
Args:
a: A set or list.
b: A set or list.
Returns:
A set containing the elements that are in both `a` and `b`.
"""
_precondition_only_sets_or_lists(a, b)
return depset([e for e in a if e in b])
def _union(*args):
"""Returns the union of several sets.
"""Returns the union of several sets.
Args:
*args: An arbitrary number of sets or lists.
Returns:
The set union of all sets or lists in `*args`.
"""
_precondition_only_sets_or_lists(*args)
args_deps = [depset(x) if type(x) == type([]) else x for x in args]
return depset(transitive=args_deps)
Args:
*args: An arbitrary number of sets or lists.
Returns:
The set union of all sets or lists in `*args`.
"""
_precondition_only_sets_or_lists(*args)
args_deps = [depset(x) if type(x) == type([]) else x for x in args]
return depset(transitive = args_deps)
def _difference(a, b):
"""Returns the elements in `a` that are not in `b`.
"""Returns the elements in `a` that are not in `b`.
Args:
a: A set or list.
b: A set or list.
Returns:
A set containing the elements that are in `a` but not in `b`.
"""
_precondition_only_sets_or_lists(a, b)
return depset([e for e in a if e not in b])
Args:
a: A set or list.
b: A set or list.
Returns:
A set containing the elements that are in `a` but not in `b`.
"""
_precondition_only_sets_or_lists(a, b)
return depset([e for e in a if e not in b])
sets = struct(
difference = _difference,

View File

@ -14,44 +14,41 @@
"""Skylib module containing shell utility functions."""
def _array_literal(iterable):
"""Creates a string from a sequence that can be used as a shell array.
"""Creates a string from a sequence that can be used as a shell array.
For example, `shell.array_literal(["a", "b", "c"])` would return the string
`("a" "b" "c")`, which can be used in a shell script wherever an array
literal is needed.
For example, `shell.array_literal(["a", "b", "c"])` would return the string
`("a" "b" "c")`, which can be used in a shell script wherever an array
literal is needed.
Note that all elements in the array are quoted (using `shell.quote`) for
safety, even if they do not need to be.
Note that all elements in the array are quoted (using `shell.quote`) for
safety, even if they do not need to be.
Args:
iterable: A sequence of elements. Elements that are not strings will be
converted to strings first, by calling `str()`.
Returns:
A string that represents the sequence as a shell array; that is,
parentheses containing the quoted elements.
"""
return "(" + " ".join([_quote(str(i)) for i in iterable]) + ")"
Args:
iterable: A sequence of elements. Elements that are not strings will be
converted to strings first, by calling `str()`.
Returns:
A string that represents the sequence as a shell array; that is,
parentheses containing the quoted elements.
"""
return "(" + " ".join([_quote(str(i)) for i in iterable]) + ")"
def _quote(s):
"""Quotes the given string for use in a shell command.
"""Quotes the given string for use in a shell command.
This function quotes the given string (in case it contains spaces or other
shell metacharacters.)
This function quotes the given string (in case it contains spaces or other
shell metacharacters.)
Args:
s: The string to quote.
Returns:
A quoted version of the string that can be passed to a shell command.
"""
return "'" + s.replace("'", "'\\''") + "'"
Args:
s: The string to quote.
Returns:
A quoted version of the string that can be passed to a shell command.
"""
return "'" + s.replace("'", "'\\''") + "'"
shell = struct(
array_literal=_array_literal,
quote=_quote,
array_literal = _array_literal,
quote = _quote,
)

View File

@ -14,24 +14,22 @@
"""Skylib module containing functions that operate on structs."""
def _to_dict(s):
"""Converts a `struct` to a `dict`.
"""Converts a `struct` to a `dict`.
Args:
s: A `struct`.
Returns:
A `dict` whose keys and values are the same as the fields in `s`. The
transformation is only applied to the struct's fields and not to any
nested values.
"""
attributes = dir(s)
attributes.remove("to_json")
attributes.remove("to_proto")
return {key: getattr(s, key) for key in attributes}
Args:
s: A `struct`.
Returns:
A `dict` whose keys and values are the same as the fields in `s`. The
transformation is only applied to the struct's fields and not to any
nested values.
"""
attributes = dir(s)
attributes.remove("to_json")
attributes.remove("to_proto")
return {key: getattr(s, key) for key in attributes}
structs = struct(
to_dict=_to_dict,
to_dict = _to_dict,
)

View File

@ -13,7 +13,6 @@
# limitations under the License.
"""Skylib module containing functions checking types."""
# create instance singletons to avoid unnecessary allocations
_a_bool = True
_a_dict = {}
@ -22,10 +21,8 @@ _a_string = ""
_a_tuple = ()
_an_int = 1
def _a_function():
pass
pass
def _is_list(v):
"""Returns True if v is an instance of a list.
@ -38,7 +35,6 @@ def _is_list(v):
"""
return type(v) == type(_a_list)
def _is_string(v):
"""Returns True if v is an instance of a string.
@ -50,7 +46,6 @@ def _is_string(v):
"""
return type(v) == type(_a_string)
def _is_bool(v):
"""Returns True if v is an instance of a bool.
@ -62,7 +57,6 @@ def _is_bool(v):
"""
return type(v) == type(_a_bool)
def _is_none(v):
"""Returns True if v has the type of None.
@ -74,7 +68,6 @@ def _is_none(v):
"""
return type(v) == type(None)
def _is_int(v):
"""Returns True if v is an instance of a signed integer.
@ -86,7 +79,6 @@ def _is_int(v):
"""
return type(v) == type(_an_int)
def _is_tuple(v):
"""Returns True if v is an instance of a tuple.
@ -98,7 +90,6 @@ def _is_tuple(v):
"""
return type(v) == type(_a_tuple)
def _is_dict(v):
"""Returns True if v is an instance of a dict.
@ -110,7 +101,6 @@ def _is_dict(v):
"""
return type(v) == type(_a_dict)
def _is_function(v):
"""Returns True if v is an instance of a function.
@ -122,14 +112,13 @@ def _is_function(v):
"""
return type(v) == type(_a_function)
types = struct(
is_list=_is_list,
is_string=_is_string,
is_bool=_is_bool,
is_none=_is_none,
is_int=_is_int,
is_tuple=_is_tuple,
is_dict=_is_dict,
is_function=_is_function,
is_list = _is_list,
is_string = _is_string,
is_bool = _is_bool,
is_none = _is_none,
is_int = _is_int,
is_tuple = _is_tuple,
is_dict = _is_dict,
is_function = _is_function,
)

View File

@ -20,272 +20,265 @@ assertions used to within tests.
"""
load(":sets.bzl", "sets")
load(":new_sets.bzl", new_sets="sets")
load(":new_sets.bzl", new_sets = "sets")
def _make(impl, attrs = None):
"""Creates a unit test rule from its implementation function.
def _make(impl, attrs=None):
"""Creates a unit test rule from its implementation function.
Each unit test is defined in an implementation function that must then be
associated with a rule so that a target can be built. This function handles
the boilerplate to create and return a test rule and captures the
implementation function's name so that it can be printed in test feedback.
Each unit test is defined in an implementation function that must then be
associated with a rule so that a target can be built. This function handles
the boilerplate to create and return a test rule and captures the
implementation function's name so that it can be printed in test feedback.
The optional `attrs` argument can be used to define dependencies for this
test, in order to form unit tests of rules.
The optional `attrs` argument can be used to define dependencies for this
test, in order to form unit tests of rules.
An example of a unit test:
An example of a unit test:
```
def _your_test(ctx):
env = unittest.begin(ctx)
```
def _your_test(ctx):
env = unittest.begin(ctx)
# Assert statements go here
# Assert statements go here
unittest.end(env)
unittest.end(env)
your_test = unittest.make(_your_test)
```
your_test = unittest.make(_your_test)
```
Recall that names of test rules must end in `_test`.
Recall that names of test rules must end in `_test`.
Args:
impl: The implementation function of the unit test.
attrs: An optional dictionary to supplement the attrs passed to the
unit test's `rule()` constructor.
Args:
impl: The implementation function of the unit test.
attrs: An optional dictionary to supplement the attrs passed to the
unit test's `rule()` constructor.
Returns:
A rule definition that should be stored in a global whose name ends in
`_test`.
"""
Returns:
A rule definition that should be stored in a global whose name ends in
`_test`.
"""
# Derive the name of the implementation function for better test feedback.
# Skylark currently stringifies a function as "<function NAME>", so we use
# that knowledge to parse the "NAME" portion out. If this behavior ever
# changes, we'll need to update this.
# TODO(bazel-team): Expose a ._name field on functions to avoid this.
impl_name = str(impl)
impl_name = impl_name.partition("<function ")[-1]
impl_name = impl_name.rpartition(">")[0]
# Derive the name of the implementation function for better test feedback.
# Skylark currently stringifies a function as "<function NAME>", so we use
# that knowledge to parse the "NAME" portion out. If this behavior ever
# changes, we'll need to update this.
# TODO(bazel-team): Expose a ._name field on functions to avoid this.
impl_name = str(impl)
impl_name = impl_name.partition("<function ")[-1]
impl_name = impl_name.rpartition(">")[0]
attrs = dict(attrs) if attrs else {}
attrs["_impl_name"] = attr.string(default=impl_name)
return rule(
impl,
attrs=attrs,
_skylark_testable=True,
test=True,
)
attrs = dict(attrs) if attrs else {}
attrs["_impl_name"] = attr.string(default = impl_name)
return rule(
impl,
attrs = attrs,
_skylark_testable = True,
test = True,
)
def _suite(name, *test_rules):
"""Defines a `test_suite` target that contains multiple tests.
"""Defines a `test_suite` target that contains multiple tests.
After defining your test rules in a `.bzl` file, you need to create targets
from those rules so that `blaze test` can execute them. Doing this manually
in a BUILD file would consist of listing each test in your `load` statement
and then creating each target one by one. To reduce duplication, we recommend
writing a macro in your `.bzl` file to instantiate all targets, and calling
that macro from your BUILD file so you only have to load one symbol.
After defining your test rules in a `.bzl` file, you need to create targets
from those rules so that `blaze test` can execute them. Doing this manually
in a BUILD file would consist of listing each test in your `load` statement
and then creating each target one by one. To reduce duplication, we recommend
writing a macro in your `.bzl` file to instantiate all targets, and calling
that macro from your BUILD file so you only have to load one symbol.
For the case where your unit tests do not take any (non-default) attributes --
i.e., if your unit tests do not test rules -- you can use this function to
create the targets and wrap them in a single test_suite target. In your
`.bzl` file, write:
For the case where your unit tests do not take any (non-default) attributes --
i.e., if your unit tests do not test rules -- you can use this function to
create the targets and wrap them in a single test_suite target. In your
`.bzl` file, write:
```
def your_test_suite():
unittest.suite(
"your_test_suite",
your_test,
your_other_test,
yet_another_test,
```
def your_test_suite():
unittest.suite(
"your_test_suite",
your_test,
your_other_test,
yet_another_test,
)
```
Then, in your `BUILD` file, simply load the macro and invoke it to have all
of the targets created:
```
load("//path/to/your/package:tests.bzl", "your_test_suite")
your_test_suite()
```
If you pass _N_ unit test rules to `unittest.suite`, _N_ + 1 targets will be
created: a `test_suite` target named `${name}` (where `${name}` is the name
argument passed in here) and targets named `${name}_test_${i}`, where `${i}`
is the index of the test in the `test_rules` list, which is used to uniquely
name each target.
Args:
name: The name of the `test_suite` target, and the prefix of all the test
target names.
*test_rules: A list of test rules defines by `unittest.test`.
"""
test_names = []
for index, test_rule in enumerate(test_rules):
test_name = "%s_test_%d" % (name, index)
test_rule(name = test_name)
test_names.append(test_name)
native.test_suite(
name = name,
tests = [":%s" % t for t in test_names],
)
```
Then, in your `BUILD` file, simply load the macro and invoke it to have all
of the targets created:
```
load("//path/to/your/package:tests.bzl", "your_test_suite")
your_test_suite()
```
If you pass _N_ unit test rules to `unittest.suite`, _N_ + 1 targets will be
created: a `test_suite` target named `${name}` (where `${name}` is the name
argument passed in here) and targets named `${name}_test_${i}`, where `${i}`
is the index of the test in the `test_rules` list, which is used to uniquely
name each target.
Args:
name: The name of the `test_suite` target, and the prefix of all the test
target names.
*test_rules: A list of test rules defines by `unittest.test`.
"""
test_names = []
for index, test_rule in enumerate(test_rules):
test_name = "%s_test_%d" % (name, index)
test_rule(name=test_name)
test_names.append(test_name)
native.test_suite(
name=name,
tests=[":%s" % t for t in test_names]
)
def _begin(ctx):
"""Begins a unit test.
"""Begins a unit test.
This should be the first function called in a unit test implementation
function. It initializes a "test environment" that is used to collect
assertion failures so that they can be reported and logged at the end of the
test.
This should be the first function called in a unit test implementation
function. It initializes a "test environment" that is used to collect
assertion failures so that they can be reported and logged at the end of the
test.
Args:
ctx: The Skylark context. Pass the implementation function's `ctx` argument
in verbatim.
Returns:
A test environment struct that must be passed to assertions and finally to
`unittest.end`. Do not rely on internal details about the fields in this
struct as it may change.
"""
return struct(ctx=ctx, failures=[])
Args:
ctx: The Skylark context. Pass the implementation function's `ctx` argument
in verbatim.
Returns:
A test environment struct that must be passed to assertions and finally to
`unittest.end`. Do not rely on internal details about the fields in this
struct as it may change.
"""
return struct(ctx = ctx, failures = [])
def _end(env):
"""Ends a unit test and logs the results.
"""Ends a unit test and logs the results.
This must be called before the end of a unit test implementation function so
that the results are reported.
Args:
env: The test environment returned by `unittest.begin`.
"""
cmd = "\n".join([
"cat << EOF",
"\n".join(env.failures),
"EOF",
"exit %d" % len(env.failures),
])
env.ctx.file_action(
output=env.ctx.outputs.executable,
content=cmd,
executable=True,
)
This must be called before the end of a unit test implementation function so
that the results are reported.
Args:
env: The test environment returned by `unittest.begin`.
"""
cmd = "\n".join([
"cat << EOF",
"\n".join(env.failures),
"EOF",
"exit %d" % len(env.failures),
])
env.ctx.file_action(
output = env.ctx.outputs.executable,
content = cmd,
executable = True,
)
def _fail(env, msg):
"""Unconditionally causes the current test to fail.
"""Unconditionally causes the current test to fail.
Args:
env: The test environment returned by `unittest.begin`.
msg: The message to log describing the failure.
"""
full_msg = "In test %s: %s" % (env.ctx.attr._impl_name, msg)
print(full_msg)
env.failures.append(full_msg)
Args:
env: The test environment returned by `unittest.begin`.
msg: The message to log describing the failure.
"""
full_msg = "In test %s: %s" % (env.ctx.attr._impl_name, msg)
print(full_msg)
env.failures.append(full_msg)
def _assert_true(
env,
condition,
msg = "Expected condition to be true, but was false."):
"""Asserts that the given `condition` is true.
def _assert_true(env,
condition,
msg="Expected condition to be true, but was false."):
"""Asserts that the given `condition` is true.
Args:
env: The test environment returned by `unittest.begin`.
condition: A value that will be evaluated in a Boolean context.
msg: An optional message that will be printed that describes the failure.
If omitted, a default will be used.
"""
if not condition:
_fail(env, msg)
Args:
env: The test environment returned by `unittest.begin`.
condition: A value that will be evaluated in a Boolean context.
msg: An optional message that will be printed that describes the failure.
If omitted, a default will be used.
"""
if not condition:
_fail(env, msg)
def _assert_false(
env,
condition,
msg = "Expected condition to be false, but was true."):
"""Asserts that the given `condition` is false.
Args:
env: The test environment returned by `unittest.begin`.
condition: A value that will be evaluated in a Boolean context.
msg: An optional message that will be printed that describes the failure.
If omitted, a default will be used.
"""
if condition:
_fail(env, msg)
def _assert_false(env,
condition,
msg="Expected condition to be false, but was true."):
"""Asserts that the given `condition` is false.
def _assert_equals(env, expected, actual, msg = None):
"""Asserts that the given `expected` and `actual` values are equal.
Args:
env: The test environment returned by `unittest.begin`.
condition: A value that will be evaluated in a Boolean context.
msg: An optional message that will be printed that describes the failure.
If omitted, a default will be used.
"""
if condition:
_fail(env, msg)
Args:
env: The test environment returned by `unittest.begin`.
expected: The expected value of some computation.
actual: The actual value returned by some computation.
msg: An optional message that will be printed that describes the failure.
If omitted, a default will be used.
"""
if expected != actual:
expectation_msg = 'Expected "%s", but got "%s"' % (expected, actual)
if msg:
full_msg = "%s (%s)" % (msg, expectation_msg)
else:
full_msg = expectation_msg
_fail(env, full_msg)
def _assert_set_equals(env, expected, actual, msg = None):
"""Asserts that the given `expected` and `actual` sets are equal.
def _assert_equals(env, expected, actual, msg=None):
"""Asserts that the given `expected` and `actual` values are equal.
Args:
env: The test environment returned by `unittest.begin`.
expected: The expected set resulting from some computation.
actual: The actual set returned by some computation.
msg: An optional message that will be printed that describes the failure.
If omitted, a default will be used.
"""
if type(actual) != type(depset()) or not sets.is_equal(expected, actual):
expectation_msg = "Expected %r, but got %r" % (expected, actual)
if msg:
full_msg = "%s (%s)" % (msg, expectation_msg)
else:
full_msg = expectation_msg
_fail(env, full_msg)
Args:
env: The test environment returned by `unittest.begin`.
expected: The expected value of some computation.
actual: The actual value returned by some computation.
msg: An optional message that will be printed that describes the failure.
If omitted, a default will be used.
"""
if expected != actual:
expectation_msg = 'Expected "%s", but got "%s"' % (expected, actual)
if msg:
full_msg = "%s (%s)" % (msg, expectation_msg)
else:
full_msg = expectation_msg
_fail(env, full_msg)
def _assert_new_set_equals(env, expected, actual, msg = None):
"""Asserts that the given `expected` and `actual` sets are equal.
def _assert_set_equals(env, expected, actual, msg=None):
"""Asserts that the given `expected` and `actual` sets are equal.
Args:
env: The test environment returned by `unittest.begin`.
expected: The expected set resulting from some computation.
actual: The actual set returned by some computation.
msg: An optional message that will be printed that describes the failure.
If omitted, a default will be used.
"""
if type(actual) != type(depset()) or not sets.is_equal(expected, actual):
expectation_msg = "Expected %r, but got %r" % (expected, actual)
if msg:
full_msg = "%s (%s)" % (msg, expectation_msg)
else:
full_msg = expectation_msg
_fail(env, full_msg)
def _assert_new_set_equals(env, expected, actual, msg=None):
"""Asserts that the given `expected` and `actual` sets are equal.
Args:
env: The test environment returned by `unittest.begin`.
expected: The expected set resulting from some computation.
actual: The actual set returned by some computation.
msg: An optional message that will be printed that describes the failure.
If omitted, a default will be used.
"""
if not new_sets.is_equal(expected, actual):
expectation_msg = "Expected %r, but got %r" % (expected, actual)
if msg:
full_msg = "%s (%s)" % (msg, expectation_msg)
else:
full_msg = expectation_msg
_fail(env, full_msg)
Args:
env: The test environment returned by `unittest.begin`.
expected: The expected set resulting from some computation.
actual: The actual set returned by some computation.
msg: An optional message that will be printed that describes the failure.
If omitted, a default will be used.
"""
if not new_sets.is_equal(expected, actual):
expectation_msg = "Expected %r, but got %r" % (expected, actual)
if msg:
full_msg = "%s (%s)" % (msg, expectation_msg)
else:
full_msg = expectation_msg
_fail(env, full_msg)
asserts = struct(
equals=_assert_equals,
false=_assert_false,
set_equals=_assert_set_equals,
equals = _assert_equals,
false = _assert_false,
set_equals = _assert_set_equals,
new_set_equals = _assert_new_set_equals,
true=_assert_true,
true = _assert_true,
)
unittest = struct(
make=_make,
suite=_suite,
begin=_begin,
end=_end,
fail=_fail,
make = _make,
suite = _suite,
begin = _begin,
end = _end,
fail = _fail,
)

View File

@ -15,111 +15,113 @@
"""Skylib module containing functions for checking Bazel versions."""
def _get_bazel_version():
"""Returns the current Bazel version"""
return native.bazel_version
"""Returns the current Bazel version"""
return native.bazel_version
def _extract_version_number(bazel_version):
"""Extracts the semantic version number from a version string
"""Extracts the semantic version number from a version string
Args:
bazel_version: the version string that begins with the semantic version
e.g. "1.2.3rc1 abc1234" where "abc1234" is a commit hash.
Args:
bazel_version: the version string that begins with the semantic version
e.g. "1.2.3rc1 abc1234" where "abc1234" is a commit hash.
Returns:
The semantic version string, like "1.2.3".
"""
for i in range(len(bazel_version)):
c = bazel_version[i]
if not (c.isdigit() or c == "."):
return bazel_version[:i]
return bazel_version
Returns:
The semantic version string, like "1.2.3".
"""
for i in range(len(bazel_version)):
c = bazel_version[i]
if not (c.isdigit() or c == "."):
return bazel_version[:i]
return bazel_version
# Parse the bazel version string from `native.bazel_version`.
# e.g.
# "0.10.0rc1 abc123d" => (0, 10, 0)
# "0.3.0" => (0, 3, 0)
def _parse_bazel_version(bazel_version):
"""Parses a version string into a 3-tuple of ints
"""Parses a version string into a 3-tuple of ints
int tuples can be compared directly using binary operators (<, >).
int tuples can be compared directly using binary operators (<, >).
Args:
bazel_version: the Bazel version string
Args:
bazel_version: the Bazel version string
Returns:
An int 3-tuple of a (major, minor, patch) version.
"""
version = _extract_version_number(bazel_version)
return tuple([int(n) for n in version.split(".")])
Returns:
An int 3-tuple of a (major, minor, patch) version.
"""
version = _extract_version_number(bazel_version)
return tuple([int(n) for n in version.split(".")])
def _is_at_most(threshold, version):
"""Check that a version is lower or equals to a threshold.
"""Check that a version is lower or equals to a threshold.
Args:
threshold: the maximum version string
version: the version string to be compared to the threshold
Returns:
True if version <= threshold.
"""
return _parse_bazel_version(version) <= _parse_bazel_version(threshold)
Args:
threshold: the maximum version string
version: the version string to be compared to the threshold
Returns:
True if version <= threshold.
"""
return _parse_bazel_version(version) <= _parse_bazel_version(threshold)
def _is_at_least(threshold, version):
"""Check that a version is higher or equals to a threshold.
"""Check that a version is higher or equals to a threshold.
Args:
threshold: the minimum version string
version: the version string to be compared to the threshold
Args:
threshold: the minimum version string
version: the version string to be compared to the threshold
Returns:
True if version >= threshold.
"""
Returns:
True if version >= threshold.
"""
return _parse_bazel_version(version) >= _parse_bazel_version(threshold)
return _parse_bazel_version(version) >= _parse_bazel_version(threshold)
def _check_bazel_version(minimum_bazel_version, maximum_bazel_version = None, bazel_version = None):
"""Check that the version of Bazel is valid within the specified range.
def _check_bazel_version(minimum_bazel_version, maximum_bazel_version=None, bazel_version=None):
"""Check that the version of Bazel is valid within the specified range.
Args:
minimum_bazel_version: minimum version of Bazel expected
maximum_bazel_version: maximum version of Bazel expected
bazel_version: the version of Bazel to check. Used for testing, defaults to native.bazel_version
"""
if not bazel_version:
if "bazel_version" not in dir(native):
fail("\nCurrent Bazel version is lower than 0.2.1, expected at least %s\n" % minimum_bazel_version)
elif not native.bazel_version:
print("\nCurrent Bazel is not a release version, cannot check for compatibility.")
print("Make sure that you are running at least Bazel %s.\n" % minimum_bazel_version)
return
else:
bazel_version = native.bazel_version
Args:
minimum_bazel_version: minimum version of Bazel expected
maximum_bazel_version: maximum version of Bazel expected
bazel_version: the version of Bazel to check. Used for testing, defaults to native.bazel_version
"""
if not bazel_version:
if "bazel_version" not in dir(native):
fail("\nCurrent Bazel version is lower than 0.2.1, expected at least %s\n" % minimum_bazel_version)
elif not native.bazel_version:
print("\nCurrent Bazel is not a release version, cannot check for compatibility.")
print("Make sure that you are running at least Bazel %s.\n" % minimum_bazel_version)
return
else:
bazel_version = native.bazel_version
if not _is_at_least(
threshold = minimum_bazel_version,
version = bazel_version,
):
fail("\nCurrent Bazel version is {}, expected at least {}\n".format(
bazel_version,
minimum_bazel_version,
))
if not _is_at_least(
threshold = minimum_bazel_version,
version = bazel_version):
fail("\nCurrent Bazel version is {}, expected at least {}\n".format(
bazel_version, minimum_bazel_version))
if maximum_bazel_version:
if not _is_at_most(
threshold = maximum_bazel_version,
version = bazel_version,
):
fail("\nCurrent Bazel version is {}, expected at most {}\n".format(
bazel_version,
maximum_bazel_version,
))
if maximum_bazel_version:
if not _is_at_most(
threshold = maximum_bazel_version,
version = bazel_version):
fail("\nCurrent Bazel version is {}, expected at most {}\n".format(
bazel_version, maximum_bazel_version))
pass
pass
versions = struct(
get=_get_bazel_version,
parse=_parse_bazel_version,
check=_check_bazel_version,
is_at_most=_is_at_most,
is_at_least=_is_at_least,
get = _get_bazel_version,
parse = _parse_bazel_version,
check = _check_bazel_version,
is_at_most = _is_at_most,
is_at_least = _is_at_least,
)

View File

@ -15,46 +15,46 @@
"""Skylib module containing a library rule for aggregating rules files."""
SkylarkLibraryInfo = provider(
'Information on contained Skylark rules.',
fields={
'srcs': 'Top level rules files.',
'transitive_srcs': 'Transitive closure of rules files required for ' +
'interpretation of the srcs',
"Information on contained Skylark rules.",
fields = {
"srcs": "Top level rules files.",
"transitive_srcs": "Transitive closure of rules files required for " +
"interpretation of the srcs",
},
)
def _skylark_library_impl(ctx):
deps_files = [depset(x.files, order="postorder") for x in ctx.attr.deps]
all_files = depset(ctx.files.srcs, order="postorder", transitive=deps_files)
return [
# All dependent files should be listed in both `files` and in `runfiles`;
# this ensures that a `skylark_library` can be referenced as `data` from
# a separate program, or from `tools` of a genrule().
DefaultInfo(
files=all_files,
runfiles=ctx.runfiles(files=list(all_files)),
),
deps_files = [depset(x.files, order = "postorder") for x in ctx.attr.deps]
all_files = depset(ctx.files.srcs, order = "postorder", transitive = deps_files)
return [
# All dependent files should be listed in both `files` and in `runfiles`;
# this ensures that a `skylark_library` can be referenced as `data` from
# a separate program, or from `tools` of a genrule().
DefaultInfo(
files = all_files,
runfiles = ctx.runfiles(files = list(all_files)),
),
# We also define our own provider struct, for aggregation and testing.
SkylarkLibraryInfo(
srcs=ctx.files.srcs,
transitive_srcs=all_files,
),
]
# We also define our own provider struct, for aggregation and testing.
SkylarkLibraryInfo(
srcs = ctx.files.srcs,
transitive_srcs = all_files,
),
]
skylark_library = rule(
implementation=_skylark_library_impl,
attrs={
implementation = _skylark_library_impl,
attrs = {
"srcs": attr.label_list(
allow_files=[".bzl"],
allow_files = [".bzl"],
),
"deps": attr.label_list(
allow_files=[".bzl"],
providers=[
allow_files = [".bzl"],
providers = [
[SkylarkLibraryInfo],
],
)
}
),
},
)
"""Creates a logical collection of Skylark .bzl files.

View File

@ -14,68 +14,99 @@
"""Unit tests for collections.bzl."""
load("//:lib.bzl", "collections", "asserts", "unittest")
load("//:lib.bzl", "asserts", "collections", "unittest")
def _after_each_test(ctx):
"""Unit tests for collections.after_each."""
env = unittest.begin(ctx)
"""Unit tests for collections.after_each."""
env = unittest.begin(ctx)
asserts.equals(env, [], collections.after_each("1", []))
asserts.equals(env, ["a", "1"], collections.after_each("1", ["a"]))
asserts.equals(env, ["a", "1", "b", "1"],
collections.after_each("1", ["a", "b"]))
asserts.equals(env, [], collections.after_each("1", []))
asserts.equals(env, ["a", "1"], collections.after_each("1", ["a"]))
asserts.equals(
env,
["a", "1", "b", "1"],
collections.after_each("1", ["a", "b"]),
)
# We don't care what type the separator is, we just put it there; so None
# should be just as valid as anything else.
asserts.equals(env, ["a", None, "b", None],
collections.after_each(None, ["a", "b"]))
# We don't care what type the separator is, we just put it there; so None
# should be just as valid as anything else.
asserts.equals(
env,
["a", None, "b", None],
collections.after_each(None, ["a", "b"]),
)
unittest.end(env)
unittest.end(env)
after_each_test = unittest.make(_after_each_test)
def _before_each_test(ctx):
"""Unit tests for collections.before_each."""
env = unittest.begin(ctx)
"""Unit tests for collections.before_each."""
env = unittest.begin(ctx)
asserts.equals(env, [], collections.before_each("1", []))
asserts.equals(env, ["1", "a"], collections.before_each("1", ["a"]))
asserts.equals(env, ["1", "a", "1", "b"],
collections.before_each("1", ["a", "b"]))
asserts.equals(env, [], collections.before_each("1", []))
asserts.equals(env, ["1", "a"], collections.before_each("1", ["a"]))
asserts.equals(
env,
["1", "a", "1", "b"],
collections.before_each("1", ["a", "b"]),
)
# We don't care what type the separator is, we just put it there; so None
# should be just as valid as anything else.
asserts.equals(env, [None, "a", None, "b"],
collections.before_each(None, ["a", "b"]))
# We don't care what type the separator is, we just put it there; so None
# should be just as valid as anything else.
asserts.equals(
env,
[None, "a", None, "b"],
collections.before_each(None, ["a", "b"]),
)
unittest.end(env)
unittest.end(env)
before_each_test = unittest.make(_before_each_test)
def _uniq_test(ctx):
env = unittest.begin(ctx)
asserts.equals(env, collections.uniq([0, 1, 2, 3]), [0, 1, 2, 3])
asserts.equals(env, collections.uniq([]), [])
asserts.equals(env, collections.uniq([1, 1, 1, 1, 1]), [1])
asserts.equals(env, collections.uniq([True, 5, "foo", 5, False, struct(a=1),
True, struct(b=2), "bar", (1,), "foo",
struct(a=1), (1,)]),
[True, 5, "foo", False, struct(a=1), struct(b=2),
"bar", (1,)])
env = unittest.begin(ctx)
asserts.equals(env, collections.uniq([0, 1, 2, 3]), [0, 1, 2, 3])
asserts.equals(env, collections.uniq([]), [])
asserts.equals(env, collections.uniq([1, 1, 1, 1, 1]), [1])
asserts.equals(
env,
collections.uniq([
True,
5,
"foo",
5,
False,
struct(a = 1),
True,
struct(b = 2),
"bar",
(1,),
"foo",
struct(a = 1),
(1,),
]),
[
True,
5,
"foo",
False,
struct(a = 1),
struct(b = 2),
"bar",
(1,),
],
)
unittest.end(env)
unittest.end(env)
uniq_test = unittest.make(_uniq_test)
def collections_test_suite():
"""Creates the test targets and test suite for collections.bzl tests."""
unittest.suite(
"collections_tests",
after_each_test,
before_each_test,
uniq_test,
)
"""Creates the test targets and test suite for collections.bzl tests."""
unittest.suite(
"collections_tests",
after_each_test,
before_each_test,
uniq_test,
)

View File

@ -14,54 +14,61 @@
"""Unit tests for dicts.bzl."""
load("//:lib.bzl", "dicts", "asserts", "unittest")
load("//:lib.bzl", "asserts", "dicts", "unittest")
def _add_test(ctx):
"""Unit tests for dicts.add."""
env = unittest.begin(ctx)
"""Unit tests for dicts.add."""
env = unittest.begin(ctx)
# Test zero- and one-argument behavior.
asserts.equals(env, {}, dicts.add())
asserts.equals(env, {"a": 1}, dicts.add({"a": 1}))
# Test zero- and one-argument behavior.
asserts.equals(env, {}, dicts.add())
asserts.equals(env, {"a": 1}, dicts.add({"a": 1}))
# Test simple two-argument behavior.
asserts.equals(env, {"a": 1, "b": 2}, dicts.add({"a": 1}, {"b": 2}))
# Test simple two-argument behavior.
asserts.equals(env, {"a": 1, "b": 2}, dicts.add({"a": 1}, {"b": 2}))
# Test simple more-than-two-argument behavior.
asserts.equals(env, {"a": 1, "b": 2, "c": 3, "d": 4},
dicts.add({"a": 1}, {"b": 2}, {"c": 3}, {"d": 4}))
# Test simple more-than-two-argument behavior.
asserts.equals(
env,
{"a": 1, "b": 2, "c": 3, "d": 4},
dicts.add({"a": 1}, {"b": 2}, {"c": 3}, {"d": 4}),
)
# Test same-key overriding.
asserts.equals(env, {"a": 100}, dicts.add({"a": 1}, {"a": 100}))
asserts.equals(env, {"a": 10}, dicts.add({"a": 1}, {"a": 100}, {"a": 10}))
asserts.equals(env, {"a": 100, "b": 10},
dicts.add({"a": 1}, {"a": 100}, {"b": 10}))
asserts.equals(env, {"a": 10}, dicts.add({"a": 1}, {}, {"a": 10}))
asserts.equals(env, {"a": 10, "b": 5},
dicts.add({"a": 1}, {"a": 10, "b": 5}))
# Test same-key overriding.
asserts.equals(env, {"a": 100}, dicts.add({"a": 1}, {"a": 100}))
asserts.equals(env, {"a": 10}, dicts.add({"a": 1}, {"a": 100}, {"a": 10}))
asserts.equals(
env,
{"a": 100, "b": 10},
dicts.add({"a": 1}, {"a": 100}, {"b": 10}),
)
asserts.equals(env, {"a": 10}, dicts.add({"a": 1}, {}, {"a": 10}))
asserts.equals(
env,
{"a": 10, "b": 5},
dicts.add({"a": 1}, {"a": 10, "b": 5}),
)
# Test some other boundary cases.
asserts.equals(env, {"a": 1}, dicts.add({"a": 1}, {}))
# Test some other boundary cases.
asserts.equals(env, {"a": 1}, dicts.add({"a": 1}, {}))
# Since dictionaries are passed around by reference, make sure that the
# result of dicts.add is always a *copy* by modifying it afterwards and
# ensuring that the original argument doesn't also reflect the change. We do
# this to protect against someone who might attempt to optimize the function
# by returning the argument itself in the one-argument case.
original = {"a": 1}
result = dicts.add(original)
result["a"] = 2
asserts.equals(env, 1, original["a"])
# Since dictionaries are passed around by reference, make sure that the
# result of dicts.add is always a *copy* by modifying it afterwards and
# ensuring that the original argument doesn't also reflect the change. We do
# this to protect against someone who might attempt to optimize the function
# by returning the argument itself in the one-argument case.
original = {"a": 1}
result = dicts.add(original)
result["a"] = 2
asserts.equals(env, 1, original["a"])
unittest.end(env)
unittest.end(env)
add_test = unittest.make(_add_test)
def dicts_test_suite():
"""Creates the test targets and test suite for dicts.bzl tests."""
unittest.suite(
"dicts_tests",
add_test,
)
"""Creates the test targets and test suite for dicts.bzl tests."""
unittest.suite(
"dicts_tests",
add_test,
)

View File

@ -14,272 +14,264 @@
"""Unit tests for new_sets.bzl."""
load("//:lib.bzl", "new_sets", "asserts", "unittest")
load("//:lib.bzl", "asserts", "new_sets", "unittest")
def _is_equal_test(ctx):
"""Unit tests for new_sets.is_equal."""
"""Unit tests for new_sets.is_equal."""
# Note that if this test fails, the results for the other `sets` tests will
# be inconclusive because they use `asserts.new_set_equals`, which in turn
# calls `new_sets.is_equal`.
env = unittest.begin(ctx)
# Note that if this test fails, the results for the other `sets` tests will
# be inconclusive because they use `asserts.new_set_equals`, which in turn
# calls `new_sets.is_equal`.
env = unittest.begin(ctx)
asserts.true(env, new_sets.is_equal(new_sets.make(), new_sets.make()))
asserts.false(env, new_sets.is_equal(new_sets.make(), new_sets.make([1])))
asserts.false(env, new_sets.is_equal(new_sets.make([1]), new_sets.make()))
asserts.true(env, new_sets.is_equal(new_sets.make([1]), new_sets.make([1])))
asserts.false(env, new_sets.is_equal(new_sets.make([1]), new_sets.make([1, 2])))
asserts.false(env, new_sets.is_equal(new_sets.make([1]), new_sets.make([2])))
asserts.false(env, new_sets.is_equal(new_sets.make([1]), new_sets.make([1, 2])))
asserts.true(env, new_sets.is_equal(new_sets.make(), new_sets.make()))
asserts.false(env, new_sets.is_equal(new_sets.make(), new_sets.make([1])))
asserts.false(env, new_sets.is_equal(new_sets.make([1]), new_sets.make()))
asserts.true(env, new_sets.is_equal(new_sets.make([1]), new_sets.make([1])))
asserts.false(env, new_sets.is_equal(new_sets.make([1]), new_sets.make([1, 2])))
asserts.false(env, new_sets.is_equal(new_sets.make([1]), new_sets.make([2])))
asserts.false(env, new_sets.is_equal(new_sets.make([1]), new_sets.make([1, 2])))
# Verify that the implementation is not using == on the sets directly.
asserts.true(env, new_sets.is_equal(new_sets.make(depset([1])), new_sets.make(depset([1]))))
# Verify that the implementation is not using == on the sets directly.
asserts.true(env, new_sets.is_equal(new_sets.make(depset([1])), new_sets.make(depset([1]))))
# If passing a list, verify that duplicate elements are ignored.
asserts.true(env, new_sets.is_equal(new_sets.make([1, 1]), new_sets.make([1])))
# If passing a list, verify that duplicate elements are ignored.
asserts.true(env, new_sets.is_equal(new_sets.make([1, 1]), new_sets.make([1])))
unittest.end(env)
unittest.end(env)
is_equal_test = unittest.make(_is_equal_test)
def _is_subset_test(ctx):
"""Unit tests for new_sets.is_subset."""
env = unittest.begin(ctx)
"""Unit tests for new_sets.is_subset."""
env = unittest.begin(ctx)
asserts.true(env, new_sets.is_subset(new_sets.make(), new_sets.make()))
asserts.true(env, new_sets.is_subset(new_sets.make(), new_sets.make([1])))
asserts.false(env, new_sets.is_subset(new_sets.make([1]), new_sets.make()))
asserts.true(env, new_sets.is_subset(new_sets.make([1]), new_sets.make([1])))
asserts.true(env, new_sets.is_subset(new_sets.make([1]), new_sets.make([1, 2])))
asserts.false(env, new_sets.is_subset(new_sets.make([1]), new_sets.make([2])))
asserts.true(env, new_sets.is_subset(new_sets.make([1]), new_sets.make(depset([1, 2]))))
asserts.true(env, new_sets.is_subset(new_sets.make(), new_sets.make()))
asserts.true(env, new_sets.is_subset(new_sets.make(), new_sets.make([1])))
asserts.false(env, new_sets.is_subset(new_sets.make([1]), new_sets.make()))
asserts.true(env, new_sets.is_subset(new_sets.make([1]), new_sets.make([1])))
asserts.true(env, new_sets.is_subset(new_sets.make([1]), new_sets.make([1, 2])))
asserts.false(env, new_sets.is_subset(new_sets.make([1]), new_sets.make([2])))
asserts.true(env, new_sets.is_subset(new_sets.make([1]), new_sets.make(depset([1, 2]))))
# If passing a list, verify that duplicate elements are ignored.
asserts.true(env, new_sets.is_subset(new_sets.make([1, 1]), new_sets.make([1, 2])))
# If passing a list, verify that duplicate elements are ignored.
asserts.true(env, new_sets.is_subset(new_sets.make([1, 1]), new_sets.make([1, 2])))
unittest.end(env)
unittest.end(env)
is_subset_test = unittest.make(_is_subset_test)
def _disjoint_test(ctx):
"""Unit tests for new_sets.disjoint."""
env = unittest.begin(ctx)
"""Unit tests for new_sets.disjoint."""
env = unittest.begin(ctx)
asserts.true(env, new_sets.disjoint(new_sets.make(), new_sets.make()))
asserts.true(env, new_sets.disjoint(new_sets.make(), new_sets.make([1])))
asserts.true(env, new_sets.disjoint(new_sets.make([1]), new_sets.make()))
asserts.false(env, new_sets.disjoint(new_sets.make([1]), new_sets.make([1])))
asserts.false(env, new_sets.disjoint(new_sets.make([1]), new_sets.make([1, 2])))
asserts.true(env, new_sets.disjoint(new_sets.make([1]), new_sets.make([2])))
asserts.true(env, new_sets.disjoint(new_sets.make([1]), new_sets.make(depset([2]))))
asserts.true(env, new_sets.disjoint(new_sets.make(), new_sets.make()))
asserts.true(env, new_sets.disjoint(new_sets.make(), new_sets.make([1])))
asserts.true(env, new_sets.disjoint(new_sets.make([1]), new_sets.make()))
asserts.false(env, new_sets.disjoint(new_sets.make([1]), new_sets.make([1])))
asserts.false(env, new_sets.disjoint(new_sets.make([1]), new_sets.make([1, 2])))
asserts.true(env, new_sets.disjoint(new_sets.make([1]), new_sets.make([2])))
asserts.true(env, new_sets.disjoint(new_sets.make([1]), new_sets.make(depset([2]))))
# If passing a list, verify that duplicate elements are ignored.
asserts.false(env, new_sets.disjoint(new_sets.make([1, 1]), new_sets.make([1, 2])))
# If passing a list, verify that duplicate elements are ignored.
asserts.false(env, new_sets.disjoint(new_sets.make([1, 1]), new_sets.make([1, 2])))
unittest.end(env)
unittest.end(env)
disjoint_test = unittest.make(_disjoint_test)
def _intersection_test(ctx):
"""Unit tests for new_sets.intersection."""
env = unittest.begin(ctx)
"""Unit tests for new_sets.intersection."""
env = unittest.begin(ctx)
asserts.new_set_equals(env, new_sets.make(), new_sets.intersection(new_sets.make(), new_sets.make()))
asserts.new_set_equals(env, new_sets.make(), new_sets.intersection(new_sets.make(), new_sets.make([1])))
asserts.new_set_equals(env, new_sets.make(), new_sets.intersection(new_sets.make([1]), new_sets.make()))
asserts.new_set_equals(env, new_sets.make([1]), new_sets.intersection(new_sets.make([1]), new_sets.make([1])))
asserts.new_set_equals(env, new_sets.make([1]), new_sets.intersection(new_sets.make([1]), new_sets.make([1, 2])))
asserts.new_set_equals(env, new_sets.make(), new_sets.intersection(new_sets.make([1]), new_sets.make([2])))
asserts.new_set_equals(env, new_sets.make([1]), new_sets.intersection(new_sets.make([1]), new_sets.make(depset([1]))))
asserts.new_set_equals(env, new_sets.make(), new_sets.intersection(new_sets.make(), new_sets.make()))
asserts.new_set_equals(env, new_sets.make(), new_sets.intersection(new_sets.make(), new_sets.make([1])))
asserts.new_set_equals(env, new_sets.make(), new_sets.intersection(new_sets.make([1]), new_sets.make()))
asserts.new_set_equals(env, new_sets.make([1]), new_sets.intersection(new_sets.make([1]), new_sets.make([1])))
asserts.new_set_equals(env, new_sets.make([1]), new_sets.intersection(new_sets.make([1]), new_sets.make([1, 2])))
asserts.new_set_equals(env, new_sets.make(), new_sets.intersection(new_sets.make([1]), new_sets.make([2])))
asserts.new_set_equals(env, new_sets.make([1]), new_sets.intersection(new_sets.make([1]), new_sets.make(depset([1]))))
# If passing a list, verify that duplicate elements are ignored.
asserts.new_set_equals(env, new_sets.make([1]), new_sets.intersection(new_sets.make([1, 1]), new_sets.make([1, 2])))
# If passing a list, verify that duplicate elements are ignored.
asserts.new_set_equals(env, new_sets.make([1]), new_sets.intersection(new_sets.make([1, 1]), new_sets.make([1, 2])))
unittest.end(env)
unittest.end(env)
intersection_test = unittest.make(_intersection_test)
def _union_test(ctx):
"""Unit tests for new_sets.union."""
env = unittest.begin(ctx)
"""Unit tests for new_sets.union."""
env = unittest.begin(ctx)
asserts.new_set_equals(env, new_sets.make(), new_sets.union())
asserts.new_set_equals(env, new_sets.make([1]), new_sets.union(new_sets.make([1])))
asserts.new_set_equals(env, new_sets.make(), new_sets.union(new_sets.make(), new_sets.make()))
asserts.new_set_equals(env, new_sets.make([1]), new_sets.union(new_sets.make(), new_sets.make([1])))
asserts.new_set_equals(env, new_sets.make([1]), new_sets.union(new_sets.make([1]), new_sets.make()))
asserts.new_set_equals(env, new_sets.make([1]), new_sets.union(new_sets.make([1]), new_sets.make([1])))
asserts.new_set_equals(env, new_sets.make([1, 2]), new_sets.union(new_sets.make([1]), new_sets.make([1, 2])))
asserts.new_set_equals(env, new_sets.make([1, 2]), new_sets.union(new_sets.make([1]), new_sets.make([2])))
asserts.new_set_equals(env, new_sets.make([1]), new_sets.union(new_sets.make([1]), new_sets.make(depset([1]))))
asserts.new_set_equals(env, new_sets.make(), new_sets.union())
asserts.new_set_equals(env, new_sets.make([1]), new_sets.union(new_sets.make([1])))
asserts.new_set_equals(env, new_sets.make(), new_sets.union(new_sets.make(), new_sets.make()))
asserts.new_set_equals(env, new_sets.make([1]), new_sets.union(new_sets.make(), new_sets.make([1])))
asserts.new_set_equals(env, new_sets.make([1]), new_sets.union(new_sets.make([1]), new_sets.make()))
asserts.new_set_equals(env, new_sets.make([1]), new_sets.union(new_sets.make([1]), new_sets.make([1])))
asserts.new_set_equals(env, new_sets.make([1, 2]), new_sets.union(new_sets.make([1]), new_sets.make([1, 2])))
asserts.new_set_equals(env, new_sets.make([1, 2]), new_sets.union(new_sets.make([1]), new_sets.make([2])))
asserts.new_set_equals(env, new_sets.make([1]), new_sets.union(new_sets.make([1]), new_sets.make(depset([1]))))
# If passing a list, verify that duplicate elements are ignored.
asserts.new_set_equals(env, new_sets.make([1, 2]), new_sets.union(new_sets.make([1, 1]), new_sets.make([1, 2])))
# If passing a list, verify that duplicate elements are ignored.
asserts.new_set_equals(env, new_sets.make([1, 2]), new_sets.union(new_sets.make([1, 1]), new_sets.make([1, 2])))
unittest.end(env)
unittest.end(env)
union_test = unittest.make(_union_test)
def _difference_test(ctx):
"""Unit tests for new_sets.difference."""
env = unittest.begin(ctx)
"""Unit tests for new_sets.difference."""
env = unittest.begin(ctx)
asserts.new_set_equals(env, new_sets.make(), new_sets.difference(new_sets.make(), new_sets.make()))
asserts.new_set_equals(env, new_sets.make(), new_sets.difference(new_sets.make(), new_sets.make([1])))
asserts.new_set_equals(env, new_sets.make([1]), new_sets.difference(new_sets.make([1]), new_sets.make()))
asserts.new_set_equals(env, new_sets.make(), new_sets.difference(new_sets.make([1]), new_sets.make([1])))
asserts.new_set_equals(env, new_sets.make(), new_sets.difference(new_sets.make([1]), new_sets.make([1, 2])))
asserts.new_set_equals(env, new_sets.make([1]), new_sets.difference(new_sets.make([1]), new_sets.make([2])))
asserts.new_set_equals(env, new_sets.make(), new_sets.difference(new_sets.make([1]), new_sets.make(depset([1]))))
asserts.new_set_equals(env, new_sets.make(), new_sets.difference(new_sets.make(), new_sets.make()))
asserts.new_set_equals(env, new_sets.make(), new_sets.difference(new_sets.make(), new_sets.make([1])))
asserts.new_set_equals(env, new_sets.make([1]), new_sets.difference(new_sets.make([1]), new_sets.make()))
asserts.new_set_equals(env, new_sets.make(), new_sets.difference(new_sets.make([1]), new_sets.make([1])))
asserts.new_set_equals(env, new_sets.make(), new_sets.difference(new_sets.make([1]), new_sets.make([1, 2])))
asserts.new_set_equals(env, new_sets.make([1]), new_sets.difference(new_sets.make([1]), new_sets.make([2])))
asserts.new_set_equals(env, new_sets.make(), new_sets.difference(new_sets.make([1]), new_sets.make(depset([1]))))
# If passing a list, verify that duplicate elements are ignored.
asserts.new_set_equals(env, new_sets.make([2]), new_sets.difference(new_sets.make([1, 2]), new_sets.make([1, 1])))
# If passing a list, verify that duplicate elements are ignored.
asserts.new_set_equals(env, new_sets.make([2]), new_sets.difference(new_sets.make([1, 2]), new_sets.make([1, 1])))
unittest.end(env)
unittest.end(env)
difference_test = unittest.make(_difference_test)
def _to_list_test(ctx):
"""Unit tests for new_sets.to_list."""
env = unittest.begin(ctx)
"""Unit tests for new_sets.to_list."""
env = unittest.begin(ctx)
asserts.equals(env, [], new_sets.to_list(new_sets.make()))
asserts.equals(env, [1], new_sets.to_list(new_sets.make([1, 1, 1])))
asserts.equals(env, [1, 2, 3], new_sets.to_list(new_sets.make([1, 2, 3])))
asserts.equals(env, [], new_sets.to_list(new_sets.make()))
asserts.equals(env, [1], new_sets.to_list(new_sets.make([1, 1, 1])))
asserts.equals(env, [1, 2, 3], new_sets.to_list(new_sets.make([1, 2, 3])))
unittest.end(env)
unittest.end(env)
to_list_test = unittest.make(_to_list_test)
def _make_test(ctx):
"""Unit tests for new_sets.make."""
env = unittest.begin(ctx)
"""Unit tests for new_sets.make."""
env = unittest.begin(ctx)
asserts.equals(env, {}, new_sets.make()._values)
asserts.equals(env, {x: None for x in [1, 2, 3]}, new_sets.make([1, 1, 2, 2, 3, 3])._values)
asserts.equals(env, {1: None, 2: None}, new_sets.make(depset([1, 2]))._values)
asserts.equals(env, {}, new_sets.make()._values)
asserts.equals(env, {x: None for x in [1, 2, 3]}, new_sets.make([1, 1, 2, 2, 3, 3])._values)
asserts.equals(env, {1: None, 2: None}, new_sets.make(depset([1, 2]))._values)
unittest.end(env)
unittest.end(env)
make_test = unittest.make(_make_test)
def _copy_test(ctx):
"""Unit tests for new_sets.copy."""
env = unittest.begin(ctx)
"""Unit tests for new_sets.copy."""
env = unittest.begin(ctx)
asserts.new_set_equals(env, new_sets.copy(new_sets.make()), new_sets.make())
asserts.new_set_equals(env, new_sets.copy(new_sets.make([1, 2, 3])), new_sets.make([1, 2, 3]))
# Ensure mutating the copy does not mutate the original
original = new_sets.make([1, 2, 3])
copy = new_sets.copy(original)
copy._values[5] = None
asserts.false(env, new_sets.is_equal(original, copy))
asserts.new_set_equals(env, new_sets.copy(new_sets.make()), new_sets.make())
asserts.new_set_equals(env, new_sets.copy(new_sets.make([1, 2, 3])), new_sets.make([1, 2, 3]))
unittest.end(env)
# Ensure mutating the copy does not mutate the original
original = new_sets.make([1, 2, 3])
copy = new_sets.copy(original)
copy._values[5] = None
asserts.false(env, new_sets.is_equal(original, copy))
unittest.end(env)
copy_test = unittest.make(_copy_test)
def _insert_test(ctx):
"""Unit tests for new_sets.insert."""
env = unittest.begin(ctx)
"""Unit tests for new_sets.insert."""
env = unittest.begin(ctx)
asserts.new_set_equals(env, new_sets.make([1, 2, 3]), new_sets.insert(new_sets.make([1, 2]), 3))
# Ensure mutating the inserted set does mutate the original set.
original = new_sets.make([1, 2, 3])
after_insert = new_sets.insert(original, 4)
asserts.new_set_equals(env, original, after_insert,
msg="Insert creates a new set which is an O(n) operation, insert should be O(1).")
asserts.new_set_equals(env, new_sets.make([1, 2, 3]), new_sets.insert(new_sets.make([1, 2]), 3))
unittest.end(env)
# Ensure mutating the inserted set does mutate the original set.
original = new_sets.make([1, 2, 3])
after_insert = new_sets.insert(original, 4)
asserts.new_set_equals(
env,
original,
after_insert,
msg = "Insert creates a new set which is an O(n) operation, insert should be O(1).",
)
unittest.end(env)
insert_test = unittest.make(_insert_test)
def _contains_test(ctx):
"""Unit tests for new_sets.contains."""
env = unittest.begin(ctx)
"""Unit tests for new_sets.contains."""
env = unittest.begin(ctx)
asserts.false(env, new_sets.contains(new_sets.make(), 1))
asserts.true(env, new_sets.contains(new_sets.make([1]), 1))
asserts.true(env, new_sets.contains(new_sets.make([1, 2]), 1))
asserts.false(env, new_sets.contains(new_sets.make([2, 3]), 1))
asserts.false(env, new_sets.contains(new_sets.make(), 1))
asserts.true(env, new_sets.contains(new_sets.make([1]), 1))
asserts.true(env, new_sets.contains(new_sets.make([1, 2]), 1))
asserts.false(env, new_sets.contains(new_sets.make([2, 3]), 1))
unittest.end(env)
unittest.end(env)
contains_test = unittest.make(_contains_test)
def _length_test(ctx):
"""Unit test for new_sets.length."""
env = unittest.begin(ctx)
"""Unit test for new_sets.length."""
env = unittest.begin(ctx)
asserts.equals(env, 0, new_sets.length(new_sets.make()))
asserts.equals(env, 1, new_sets.length(new_sets.make([1])))
asserts.equals(env, 2, new_sets.length(new_sets.make([1, 2])))
asserts.equals(env, 0, new_sets.length(new_sets.make()))
asserts.equals(env, 1, new_sets.length(new_sets.make([1])))
asserts.equals(env, 2, new_sets.length(new_sets.make([1, 2])))
unittest.end(env)
unittest.end(env)
length_test = unittest.make(_length_test)
def _remove_test(ctx):
"""Unit test for new_sets.remove."""
env = unittest.begin(ctx)
"""Unit test for new_sets.remove."""
env = unittest.begin(ctx)
asserts.new_set_equals(env, new_sets.make([1, 2]), new_sets.remove(new_sets.make([1, 2, 3]), 3))
# Ensure mutating the inserted set does mutate the original set.
original = new_sets.make([1, 2, 3])
after_removal = new_sets.remove(original, 3)
asserts.new_set_equals(env, original, after_removal)
asserts.new_set_equals(env, new_sets.make([1, 2]), new_sets.remove(new_sets.make([1, 2, 3]), 3))
unittest.end(env)
# Ensure mutating the inserted set does mutate the original set.
original = new_sets.make([1, 2, 3])
after_removal = new_sets.remove(original, 3)
asserts.new_set_equals(env, original, after_removal)
unittest.end(env)
remove_test = unittest.make(_remove_test)
def _repr_str_test(ctx):
"""Unit test for new_sets.repr and new_sets.str."""
env = unittest.begin(ctx)
"""Unit test for new_sets.repr and new_sets.str."""
env = unittest.begin(ctx)
asserts.equals(env, "[]", new_sets.repr(new_sets.make()))
asserts.equals(env, "[1]", new_sets.repr(new_sets.make([1])))
asserts.equals(env, "[1, 2]", new_sets.repr(new_sets.make([1, 2])))
asserts.equals(env, "[]", new_sets.repr(new_sets.make()))
asserts.equals(env, "[1]", new_sets.repr(new_sets.make([1])))
asserts.equals(env, "[1, 2]", new_sets.repr(new_sets.make([1, 2])))
asserts.equals(env, "[]", new_sets.str(new_sets.make()))
asserts.equals(env, "[1]", new_sets.str(new_sets.make([1])))
asserts.equals(env, "[1, 2]", new_sets.str(new_sets.make([1, 2])))
asserts.equals(env, "[]", new_sets.str(new_sets.make()))
asserts.equals(env, "[1]", new_sets.str(new_sets.make([1])))
asserts.equals(env, "[1, 2]", new_sets.str(new_sets.make([1, 2])))
unittest.end(env)
unittest.end(env)
repr_str_test = unittest.make(_repr_str_test)
def new_sets_test_suite():
"""Creates the test targets and test suite for new_sets.bzl tests."""
unittest.suite(
"new_sets_tests",
disjoint_test,
intersection_test,
is_equal_test,
is_subset_test,
difference_test,
union_test,
to_list_test,
make_test,
copy_test,
insert_test,
contains_test,
length_test,
remove_test,
repr_str_test,
)
"""Creates the test targets and test suite for new_sets.bzl tests."""
unittest.suite(
"new_sets_tests",
disjoint_test,
intersection_test,
is_equal_test,
is_subset_test,
difference_test,
union_test,
to_list_test,
make_test,
copy_test,
insert_test,
contains_test,
length_test,
remove_test,
repr_str_test,
)

View File

@ -14,72 +14,70 @@
"""Unit tests for partial.bzl."""
load("//:lib.bzl", "partial", "asserts", "unittest")
load("//:lib.bzl", "asserts", "partial", "unittest")
def _make_noargs_nokwargs():
"""Test utility for no args no kwargs case"""
return 1
"""Test utility for no args no kwargs case"""
return 1
def _make_args_nokwargs(arg1, arg2, arg3):
"""Test utility for args no kwargs case"""
return arg1 + arg2 + arg3
"""Test utility for args no kwargs case"""
return arg1 + arg2 + arg3
def _make_args_kwargs(arg1, arg2, arg3, **kwargs):
"""Test utility for args and kwargs case"""
return arg1 + arg2 + arg3 + kwargs["x"] + kwargs["y"]
"""Test utility for args and kwargs case"""
return arg1 + arg2 + arg3 + kwargs["x"] + kwargs["y"]
def _call_noargs_nokwargs(call_arg1):
"""Test utility no args no kwargs case where values passed from call site"""
return call_arg1;
"""Test utility no args no kwargs case where values passed from call site"""
return call_arg1
def _call_args_nokwargs(func_arg1, call_arg1):
"""Test utility for args no kwargs case where values passed from call site"""
return func_arg1 + call_arg1;
"""Test utility for args no kwargs case where values passed from call site"""
return func_arg1 + call_arg1
def _call_args_kwargs(func_arg1, call_arg1, func_mult, call_mult):
"""Test utility for args and kwargs case where values passed from call site"""
return (func_arg1 + call_arg1) * func_mult * call_mult;
"""Test utility for args and kwargs case where values passed from call site"""
return (func_arg1 + call_arg1) * func_mult * call_mult
def _make_call_test(ctx):
"""Unit tests for partial.make and partial.call."""
env = unittest.begin(ctx)
"""Unit tests for partial.make and partial.call."""
env = unittest.begin(ctx)
# Test cases where there are no args (or kwargs) at the make site, only
# at the call site.
foo = partial.make(_make_noargs_nokwargs)
asserts.equals(env, 1, partial.call(foo))
# Test cases where there are no args (or kwargs) at the make site, only
# at the call site.
foo = partial.make(_make_noargs_nokwargs)
asserts.equals(env, 1, partial.call(foo))
foo = partial.make(_make_args_nokwargs)
asserts.equals(env, 6, partial.call(foo, 1, 2, 3))
foo = partial.make(_make_args_nokwargs)
asserts.equals(env, 6, partial.call(foo, 1, 2, 3))
foo = partial.make(_make_args_kwargs)
asserts.equals(env, 15, partial.call(foo, 1, 2, 3, x=4, y=5))
foo = partial.make(_make_args_kwargs)
asserts.equals(env, 15, partial.call(foo, 1, 2, 3, x = 4, y = 5))
# Test cases where there are args (and/or kwargs) at the make site and the
# call site.
foo = partial.make(_call_noargs_nokwargs, 100)
asserts.equals(env, 100, partial.call(foo))
# Test cases where there are args (and/or kwargs) at the make site and the
# call site.
foo = partial.make(_call_noargs_nokwargs, 100)
asserts.equals(env, 100, partial.call(foo))
foo = partial.make(_call_args_nokwargs, 100)
asserts.equals(env, 112, partial.call(foo, 12))
foo = partial.make(_call_args_nokwargs, 100)
asserts.equals(env, 112, partial.call(foo, 12))
foo = partial.make(_call_args_kwargs, 100, func_mult=10)
asserts.equals(env, 2240, partial.call(foo, 12, call_mult=2))
foo = partial.make(_call_args_kwargs, 100, func_mult = 10)
asserts.equals(env, 2240, partial.call(foo, 12, call_mult = 2))
# Test case where there are args and kwargs ath the make site, and the call
# site overrides some make site args.
foo = partial.make(_call_args_kwargs, 100, func_mult=10)
asserts.equals(env, 1120, partial.call(foo, 12, func_mult=5, call_mult=2))
# Test case where there are args and kwargs ath the make site, and the call
# site overrides some make site args.
foo = partial.make(_call_args_kwargs, 100, func_mult = 10)
asserts.equals(env, 1120, partial.call(foo, 12, func_mult = 5, call_mult = 2))
unittest.end(env)
unittest.end(env)
make_call_test = unittest.make(_make_call_test)
def partial_test_suite():
"""Creates the test targets and test suite for partial.bzl tests."""
unittest.suite(
"partial_tests",
make_call_test,
)
"""Creates the test targets and test suite for partial.bzl tests."""
unittest.suite(
"partial_tests",
make_call_test,
)

View File

@ -14,271 +14,271 @@
"""Unit tests for paths.bzl."""
load("//:lib.bzl", "paths", "asserts", "unittest")
load("//:lib.bzl", "asserts", "paths", "unittest")
def _basename_test(ctx):
"""Unit tests for paths.basename."""
env = unittest.begin(ctx)
"""Unit tests for paths.basename."""
env = unittest.begin(ctx)
# Verify some degenerate cases.
asserts.equals(env, "", paths.basename(""))
asserts.equals(env, "", paths.basename("/"))
asserts.equals(env, "bar", paths.basename("foo///bar"))
# Verify some degenerate cases.
asserts.equals(env, "", paths.basename(""))
asserts.equals(env, "", paths.basename("/"))
asserts.equals(env, "bar", paths.basename("foo///bar"))
# Verify some realistic cases.
asserts.equals(env, "foo", paths.basename("foo"))
asserts.equals(env, "foo", paths.basename("/foo"))
asserts.equals(env, "foo", paths.basename("bar/foo"))
asserts.equals(env, "foo", paths.basename("/bar/foo"))
# Verify some realistic cases.
asserts.equals(env, "foo", paths.basename("foo"))
asserts.equals(env, "foo", paths.basename("/foo"))
asserts.equals(env, "foo", paths.basename("bar/foo"))
asserts.equals(env, "foo", paths.basename("/bar/foo"))
# Verify that we correctly duplicate Python's os.path.basename behavior,
# where a trailing slash means the basename is empty.
asserts.equals(env, "", paths.basename("foo/"))
asserts.equals(env, "", paths.basename("/foo/"))
# Verify that we correctly duplicate Python's os.path.basename behavior,
# where a trailing slash means the basename is empty.
asserts.equals(env, "", paths.basename("foo/"))
asserts.equals(env, "", paths.basename("/foo/"))
unittest.end(env)
unittest.end(env)
basename_test = unittest.make(_basename_test)
def _dirname_test(ctx):
"""Unit tests for paths.dirname."""
env = unittest.begin(ctx)
"""Unit tests for paths.dirname."""
env = unittest.begin(ctx)
# Verify some degenerate cases.
asserts.equals(env, "", paths.dirname(""))
asserts.equals(env, "/", paths.dirname("/"))
asserts.equals(env, "foo", paths.dirname("foo///bar"))
# Verify some degenerate cases.
asserts.equals(env, "", paths.dirname(""))
asserts.equals(env, "/", paths.dirname("/"))
asserts.equals(env, "foo", paths.dirname("foo///bar"))
# Verify some realistic cases.
asserts.equals(env, "", paths.dirname("foo"))
asserts.equals(env, "/", paths.dirname("/foo"))
asserts.equals(env, "bar", paths.dirname("bar/foo"))
asserts.equals(env, "/bar", paths.dirname("/bar/foo"))
# Verify some realistic cases.
asserts.equals(env, "", paths.dirname("foo"))
asserts.equals(env, "/", paths.dirname("/foo"))
asserts.equals(env, "bar", paths.dirname("bar/foo"))
asserts.equals(env, "/bar", paths.dirname("/bar/foo"))
# Verify that we correctly duplicate Python's os.path.dirname behavior,
# where a trailing slash means the dirname is the same as the original
# path (without the trailing slash).
asserts.equals(env, "foo", paths.dirname("foo/"))
asserts.equals(env, "/foo", paths.dirname("/foo/"))
# Verify that we correctly duplicate Python's os.path.dirname behavior,
# where a trailing slash means the dirname is the same as the original
# path (without the trailing slash).
asserts.equals(env, "foo", paths.dirname("foo/"))
asserts.equals(env, "/foo", paths.dirname("/foo/"))
unittest.end(env)
unittest.end(env)
dirname_test = unittest.make(_dirname_test)
def _is_absolute_test(ctx):
"""Unit tests for paths.is_absolute."""
env = unittest.begin(ctx)
"""Unit tests for paths.is_absolute."""
env = unittest.begin(ctx)
# Try a degenerate case.
asserts.false(env, paths.is_absolute(""))
# Try a degenerate case.
asserts.false(env, paths.is_absolute(""))
# Try some relative paths.
asserts.false(env, paths.is_absolute("foo"))
asserts.false(env, paths.is_absolute("foo/"))
asserts.false(env, paths.is_absolute("foo/bar"))
# Try some relative paths.
asserts.false(env, paths.is_absolute("foo"))
asserts.false(env, paths.is_absolute("foo/"))
asserts.false(env, paths.is_absolute("foo/bar"))
# Try some absolute paths.
asserts.true(env, paths.is_absolute("/"))
asserts.true(env, paths.is_absolute("/foo"))
asserts.true(env, paths.is_absolute("/foo/"))
asserts.true(env, paths.is_absolute("/foo/bar"))
# Try some absolute paths.
asserts.true(env, paths.is_absolute("/"))
asserts.true(env, paths.is_absolute("/foo"))
asserts.true(env, paths.is_absolute("/foo/"))
asserts.true(env, paths.is_absolute("/foo/bar"))
unittest.end(env)
unittest.end(env)
is_absolute_test = unittest.make(_is_absolute_test)
def _join_test(ctx):
"""Unit tests for paths.join."""
env = unittest.begin(ctx)
"""Unit tests for paths.join."""
env = unittest.begin(ctx)
# Try a degenerate case.
asserts.equals(env, "", paths.join(""))
# Try a degenerate case.
asserts.equals(env, "", paths.join(""))
# Try some basic paths.
asserts.equals(env, "foo", paths.join("foo"))
asserts.equals(env, "foo/bar", paths.join("foo", "bar"))
asserts.equals(env, "foo/bar/baz", paths.join("foo", "bar", "baz"))
# Try some basic paths.
asserts.equals(env, "foo", paths.join("foo"))
asserts.equals(env, "foo/bar", paths.join("foo", "bar"))
asserts.equals(env, "foo/bar/baz", paths.join("foo", "bar", "baz"))
# Make sure an initially absolute path stays absolute.
asserts.equals(env, "/foo", paths.join("/foo"))
asserts.equals(env, "/foo/bar", paths.join("/foo", "bar"))
# Make sure an initially absolute path stays absolute.
asserts.equals(env, "/foo", paths.join("/foo"))
asserts.equals(env, "/foo/bar", paths.join("/foo", "bar"))
# Make sure an absolute path later in the list resets the result.
asserts.equals(env, "/baz", paths.join("foo", "bar", "/baz"))
asserts.equals(env, "/baz", paths.join("foo", "/bar", "/baz"))
asserts.equals(env, "/bar/baz", paths.join("foo", "/bar", "baz"))
asserts.equals(env, "/bar", paths.join("/foo", "/bar"))
# Make sure an absolute path later in the list resets the result.
asserts.equals(env, "/baz", paths.join("foo", "bar", "/baz"))
asserts.equals(env, "/baz", paths.join("foo", "/bar", "/baz"))
asserts.equals(env, "/bar/baz", paths.join("foo", "/bar", "baz"))
asserts.equals(env, "/bar", paths.join("/foo", "/bar"))
# Make sure a leading empty segment doesn't make it absolute.
asserts.equals(env, "foo", paths.join("", "foo"))
# Make sure a leading empty segment doesn't make it absolute.
asserts.equals(env, "foo", paths.join("", "foo"))
# Try some trailing slash scenarios.
asserts.equals(env, "foo/", paths.join("foo", ""))
asserts.equals(env, "foo/", paths.join("foo/"))
asserts.equals(env, "foo/", paths.join("foo/", ""))
asserts.equals(env, "foo//", paths.join("foo//", ""))
asserts.equals(env, "foo//", paths.join("foo//"))
asserts.equals(env, "foo/bar/baz/", paths.join("foo/", "bar/", "baz", ""))
asserts.equals(env, "foo/bar/baz/", paths.join("foo/", "bar/", "baz/"))
asserts.equals(env, "foo/bar/baz/", paths.join("foo/", "bar/", "baz/", ""))
# Try some trailing slash scenarios.
asserts.equals(env, "foo/", paths.join("foo", ""))
asserts.equals(env, "foo/", paths.join("foo/"))
asserts.equals(env, "foo/", paths.join("foo/", ""))
asserts.equals(env, "foo//", paths.join("foo//", ""))
asserts.equals(env, "foo//", paths.join("foo//"))
asserts.equals(env, "foo/bar/baz/", paths.join("foo/", "bar/", "baz", ""))
asserts.equals(env, "foo/bar/baz/", paths.join("foo/", "bar/", "baz/"))
asserts.equals(env, "foo/bar/baz/", paths.join("foo/", "bar/", "baz/", ""))
# Make sure that adjacent empty segments don't add extra path separators.
asserts.equals(env, "foo/", paths.join("foo", "", ""))
asserts.equals(env, "foo", paths.join("", "", "foo"))
asserts.equals(env, "foo/bar", paths.join("foo", "", "", "bar"))
# Make sure that adjacent empty segments don't add extra path separators.
asserts.equals(env, "foo/", paths.join("foo", "", ""))
asserts.equals(env, "foo", paths.join("", "", "foo"))
asserts.equals(env, "foo/bar", paths.join("foo", "", "", "bar"))
unittest.end(env)
unittest.end(env)
join_test = unittest.make(_join_test)
def _normalize_test(ctx):
"""Unit tests for paths.normalize."""
env = unittest.begin(ctx)
"""Unit tests for paths.normalize."""
env = unittest.begin(ctx)
# Try the most basic case.
asserts.equals(env, ".", paths.normalize(""))
# Try the most basic case.
asserts.equals(env, ".", paths.normalize(""))
# Try some basic adjacent-slash removal.
asserts.equals(env, "foo/bar", paths.normalize("foo//bar"))
asserts.equals(env, "foo/bar", paths.normalize("foo////bar"))
# Try some basic adjacent-slash removal.
asserts.equals(env, "foo/bar", paths.normalize("foo//bar"))
asserts.equals(env, "foo/bar", paths.normalize("foo////bar"))
# Try some "." removal.
asserts.equals(env, "foo/bar", paths.normalize("foo/./bar"))
asserts.equals(env, "foo/bar", paths.normalize("./foo/bar"))
asserts.equals(env, "foo/bar", paths.normalize("foo/bar/."))
asserts.equals(env, "/", paths.normalize("/."))
# Try some "." removal.
asserts.equals(env, "foo/bar", paths.normalize("foo/./bar"))
asserts.equals(env, "foo/bar", paths.normalize("./foo/bar"))
asserts.equals(env, "foo/bar", paths.normalize("foo/bar/."))
asserts.equals(env, "/", paths.normalize("/."))
# Try some ".." removal.
asserts.equals(env, "bar", paths.normalize("foo/../bar"))
asserts.equals(env, "foo", paths.normalize("foo/bar/.."))
asserts.equals(env, ".", paths.normalize("foo/.."))
asserts.equals(env, ".", paths.normalize("foo/bar/../.."))
asserts.equals(env, "..", paths.normalize("foo/../.."))
asserts.equals(env, "/", paths.normalize("/foo/../.."))
asserts.equals(env, "../../c", paths.normalize("a/b/../../../../c/d/.."))
# Try some ".." removal.
asserts.equals(env, "bar", paths.normalize("foo/../bar"))
asserts.equals(env, "foo", paths.normalize("foo/bar/.."))
asserts.equals(env, ".", paths.normalize("foo/.."))
asserts.equals(env, ".", paths.normalize("foo/bar/../.."))
asserts.equals(env, "..", paths.normalize("foo/../.."))
asserts.equals(env, "/", paths.normalize("/foo/../.."))
asserts.equals(env, "../../c", paths.normalize("a/b/../../../../c/d/.."))
# Make sure one or two initial slashes are preserved, but three or more are
# collapsed to a single slash.
asserts.equals(env, "/foo", paths.normalize("/foo"))
asserts.equals(env, "//foo", paths.normalize("//foo"))
asserts.equals(env, "/foo", paths.normalize("///foo"))
# Make sure one or two initial slashes are preserved, but three or more are
# collapsed to a single slash.
asserts.equals(env, "/foo", paths.normalize("/foo"))
asserts.equals(env, "//foo", paths.normalize("//foo"))
asserts.equals(env, "/foo", paths.normalize("///foo"))
# Trailing slashes should be removed unless the entire path is a trailing
# slash.
asserts.equals(env, "/", paths.normalize("/"))
asserts.equals(env, "foo", paths.normalize("foo/"))
asserts.equals(env, "foo/bar", paths.normalize("foo/bar/"))
# Trailing slashes should be removed unless the entire path is a trailing
# slash.
asserts.equals(env, "/", paths.normalize("/"))
asserts.equals(env, "foo", paths.normalize("foo/"))
asserts.equals(env, "foo/bar", paths.normalize("foo/bar/"))
unittest.end(env)
unittest.end(env)
normalize_test = unittest.make(_normalize_test)
def _relativize_test(ctx):
"""Unit tests for paths.relativize."""
env = unittest.begin(ctx)
"""Unit tests for paths.relativize."""
env = unittest.begin(ctx)
# Make sure that relative-to-current-directory works in all forms.
asserts.equals(env, "foo", paths.relativize("foo", ""))
asserts.equals(env, "foo", paths.relativize("foo", "."))
# Make sure that relative-to-current-directory works in all forms.
asserts.equals(env, "foo", paths.relativize("foo", ""))
asserts.equals(env, "foo", paths.relativize("foo", "."))
# Try some regular cases.
asserts.equals(env, "bar", paths.relativize("foo/bar", "foo"))
asserts.equals(env, "baz", paths.relativize("foo/bar/baz", "foo/bar"))
asserts.equals(env, "bar/baz", paths.relativize("foo/bar/baz", "foo"))
# Try some regular cases.
asserts.equals(env, "bar", paths.relativize("foo/bar", "foo"))
asserts.equals(env, "baz", paths.relativize("foo/bar/baz", "foo/bar"))
asserts.equals(env, "bar/baz", paths.relativize("foo/bar/baz", "foo"))
# Try a case where a parent directory is normalized away.
asserts.equals(env, "baz", paths.relativize("foo/bar/../baz", "foo"))
# Try a case where a parent directory is normalized away.
asserts.equals(env, "baz", paths.relativize("foo/bar/../baz", "foo"))
# Relative paths work, as long as they share a common start.
asserts.equals(env, "file", paths.relativize("../foo/bar/baz/file", "../foo/bar/baz"))
asserts.equals(env, "baz/file", paths.relativize("../foo/bar/baz/file", "../foo/bar"))
# Relative paths work, as long as they share a common start.
asserts.equals(env, "file", paths.relativize("../foo/bar/baz/file", "../foo/bar/baz"))
asserts.equals(env, "baz/file", paths.relativize("../foo/bar/baz/file", "../foo/bar"))
# TODO(allevato): Test failure cases, once that is possible.
# TODO(allevato): Test failure cases, once that is possible.
unittest.end(env)
unittest.end(env)
relativize_test = unittest.make(_relativize_test)
def _replace_extension_test(ctx):
"""Unit tests for paths.replace_extension."""
env = unittest.begin(ctx)
"""Unit tests for paths.replace_extension."""
env = unittest.begin(ctx)
# Try some degenerate cases.
asserts.equals(env, ".foo", paths.replace_extension("", ".foo"))
asserts.equals(env, "/.foo", paths.replace_extension("/", ".foo"))
asserts.equals(env, "foo.bar", paths.replace_extension("foo", ".bar"))
# Try some degenerate cases.
asserts.equals(env, ".foo", paths.replace_extension("", ".foo"))
asserts.equals(env, "/.foo", paths.replace_extension("/", ".foo"))
asserts.equals(env, "foo.bar", paths.replace_extension("foo", ".bar"))
# Try a directory with an extension and basename that doesn't have one.
asserts.equals(env, "foo.bar/baz.quux",
paths.replace_extension("foo.bar/baz", ".quux"))
# Try a directory with an extension and basename that doesn't have one.
asserts.equals(
env,
"foo.bar/baz.quux",
paths.replace_extension("foo.bar/baz", ".quux"),
)
# Now try some things with legit extensions.
asserts.equals(env, "a.z", paths.replace_extension("a.b", ".z"))
asserts.equals(env, "a.b.z", paths.replace_extension("a.b.c", ".z"))
asserts.equals(env, "a/b.z", paths.replace_extension("a/b.c", ".z"))
asserts.equals(env, "a.b/c.z", paths.replace_extension("a.b/c.d", ".z"))
asserts.equals(env, ".a/b.z", paths.replace_extension(".a/b.c", ".z"))
asserts.equals(env, ".a.z", paths.replace_extension(".a.b", ".z"))
# Now try some things with legit extensions.
asserts.equals(env, "a.z", paths.replace_extension("a.b", ".z"))
asserts.equals(env, "a.b.z", paths.replace_extension("a.b.c", ".z"))
asserts.equals(env, "a/b.z", paths.replace_extension("a/b.c", ".z"))
asserts.equals(env, "a.b/c.z", paths.replace_extension("a.b/c.d", ".z"))
asserts.equals(env, ".a/b.z", paths.replace_extension(".a/b.c", ".z"))
asserts.equals(env, ".a.z", paths.replace_extension(".a.b", ".z"))
# Verify that we don't insert a period on the extension if none is provided.
asserts.equals(env, "foobaz", paths.replace_extension("foo.bar", "baz"))
# Verify that we don't insert a period on the extension if none is provided.
asserts.equals(env, "foobaz", paths.replace_extension("foo.bar", "baz"))
unittest.end(env)
unittest.end(env)
replace_extension_test = unittest.make(_replace_extension_test)
def _split_extension_test(ctx):
"""Unit tests for paths.split_extension."""
env = unittest.begin(ctx)
"""Unit tests for paths.split_extension."""
env = unittest.begin(ctx)
# Try some degenerate cases.
asserts.equals(env, ("", ""), paths.split_extension(""))
asserts.equals(env, ("/", ""), paths.split_extension("/"))
asserts.equals(env, ("foo", ""), paths.split_extension("foo"))
# Try some degenerate cases.
asserts.equals(env, ("", ""), paths.split_extension(""))
asserts.equals(env, ("/", ""), paths.split_extension("/"))
asserts.equals(env, ("foo", ""), paths.split_extension("foo"))
# Try some paths whose basenames start with ".".
asserts.equals(env, (".", ""), paths.split_extension("."))
asserts.equals(env, (".bashrc", ""), paths.split_extension(".bashrc"))
asserts.equals(env, ("foo/.bashrc", ""), paths.split_extension("foo/.bashrc"))
asserts.equals(env, (".foo/.bashrc", ""),
paths.split_extension(".foo/.bashrc"))
# Try some paths whose basenames start with ".".
asserts.equals(env, (".", ""), paths.split_extension("."))
asserts.equals(env, (".bashrc", ""), paths.split_extension(".bashrc"))
asserts.equals(env, ("foo/.bashrc", ""), paths.split_extension("foo/.bashrc"))
asserts.equals(
env,
(".foo/.bashrc", ""),
paths.split_extension(".foo/.bashrc"),
)
# Try some directories with extensions with basenames that don't have one.
asserts.equals(env, ("foo.bar/baz", ""), paths.split_extension("foo.bar/baz"))
asserts.equals(env, ("foo.bar/.bashrc", ""),
paths.split_extension("foo.bar/.bashrc"))
# Try some directories with extensions with basenames that don't have one.
asserts.equals(env, ("foo.bar/baz", ""), paths.split_extension("foo.bar/baz"))
asserts.equals(
env,
("foo.bar/.bashrc", ""),
paths.split_extension("foo.bar/.bashrc"),
)
# Now try some things that will actually get split.
asserts.equals(env, ("a", ".b"), paths.split_extension("a.b"))
asserts.equals(env, ("a.b", ".c"), paths.split_extension("a.b.c"))
asserts.equals(env, ("a/b", ".c"), paths.split_extension("a/b.c"))
asserts.equals(env, ("a.b/c", ".d"), paths.split_extension("a.b/c.d"))
asserts.equals(env, (".a/b", ".c"), paths.split_extension(".a/b.c"))
asserts.equals(env, (".a", ".b"), paths.split_extension(".a.b"))
# Now try some things that will actually get split.
asserts.equals(env, ("a", ".b"), paths.split_extension("a.b"))
asserts.equals(env, ("a.b", ".c"), paths.split_extension("a.b.c"))
asserts.equals(env, ("a/b", ".c"), paths.split_extension("a/b.c"))
asserts.equals(env, ("a.b/c", ".d"), paths.split_extension("a.b/c.d"))
asserts.equals(env, (".a/b", ".c"), paths.split_extension(".a/b.c"))
asserts.equals(env, (".a", ".b"), paths.split_extension(".a.b"))
unittest.end(env)
unittest.end(env)
split_extension_test = unittest.make(_split_extension_test)
def paths_test_suite():
"""Creates the test targets and test suite for paths.bzl tests."""
unittest.suite(
"paths_tests",
basename_test,
dirname_test,
is_absolute_test,
join_test,
normalize_test,
relativize_test,
replace_extension_test,
split_extension_test,
)
"""Creates the test targets and test suite for paths.bzl tests."""
unittest.suite(
"paths_tests",
basename_test,
dirname_test,
is_absolute_test,
join_test,
normalize_test,
relativize_test,
replace_extension_test,
split_extension_test,
)

View File

@ -14,40 +14,51 @@
"""Unit tests for selects.bzl."""
load("//:lib.bzl", "selects", "asserts", "unittest")
load("//:lib.bzl", "asserts", "selects", "unittest")
def _with_or_test(ctx):
"""Unit tests for with_or."""
env = unittest.begin(ctx)
"""Unit tests for with_or."""
env = unittest.begin(ctx)
# We actually test on with_or_dict because Skylark can't get the
# dictionary from a select().
# We actually test on with_or_dict because Skylark can't get the
# dictionary from a select().
# Test select()-compatible input syntax.
input_dict = {":foo": ":d1", "//conditions:default": ":d1"}
asserts.equals(env, input_dict, selects.with_or_dict(input_dict))
# Test select()-compatible input syntax.
input_dict = {":foo": ":d1", "//conditions:default": ":d1"}
asserts.equals(env, input_dict, selects.with_or_dict(input_dict))
# Test OR syntax.
or_dict = {(":foo", ":bar"): ":d1"}
asserts.equals(env, {":foo": ":d1", ":bar": ":d1"},
selects.with_or_dict(or_dict))
# Test OR syntax.
or_dict = {(":foo", ":bar"): ":d1"}
asserts.equals(
env,
{":foo": ":d1", ":bar": ":d1"},
selects.with_or_dict(or_dict),
)
# Test mixed syntax.
mixed_dict = {":foo": ":d1", (":bar", ":baz"): ":d2",
"//conditions:default": ":d3"}
asserts.equals(env, {":foo": ":d1", ":bar": ":d2", ":baz": ":d2",
"//conditions:default": ":d3"},
selects.with_or_dict(mixed_dict))
# Test mixed syntax.
mixed_dict = {
":foo": ":d1",
(":bar", ":baz"): ":d2",
"//conditions:default": ":d3",
}
asserts.equals(
env,
{
":foo": ":d1",
":bar": ":d2",
":baz": ":d2",
"//conditions:default": ":d3",
},
selects.with_or_dict(mixed_dict),
)
unittest.end(env)
unittest.end(env)
with_or_test = unittest.make(_with_or_test)
def selects_test_suite():
"""Creates the test targets and test suite for selects.bzl tests."""
unittest.suite(
"selects_tests",
with_or_test,
)
"""Creates the test targets and test suite for selects.bzl tests."""
unittest.suite(
"selects_tests",
with_or_test,
)

View File

@ -14,146 +14,139 @@
"""Unit tests for sets.bzl."""
load("//:lib.bzl", "sets", "asserts", "unittest")
load("//:lib.bzl", "asserts", "sets", "unittest")
def _is_equal_test(ctx):
"""Unit tests for sets.is_equal."""
"""Unit tests for sets.is_equal."""
# Note that if this test fails, the results for the other `sets` tests will
# be inconclusive because they use `asserts.set_equals`, which in turn calls
# `sets.is_equal`.
env = unittest.begin(ctx)
# Note that if this test fails, the results for the other `sets` tests will
# be inconclusive because they use `asserts.set_equals`, which in turn calls
# `sets.is_equal`.
env = unittest.begin(ctx)
asserts.true(env, sets.is_equal([], []))
asserts.false(env, sets.is_equal([], [1]))
asserts.false(env, sets.is_equal([1], []))
asserts.true(env, sets.is_equal([1], [1]))
asserts.false(env, sets.is_equal([1], [1, 2]))
asserts.false(env, sets.is_equal([1], [2]))
asserts.false(env, sets.is_equal([1], depset([1, 2])))
asserts.true(env, sets.is_equal([], []))
asserts.false(env, sets.is_equal([], [1]))
asserts.false(env, sets.is_equal([1], []))
asserts.true(env, sets.is_equal([1], [1]))
asserts.false(env, sets.is_equal([1], [1, 2]))
asserts.false(env, sets.is_equal([1], [2]))
asserts.false(env, sets.is_equal([1], depset([1, 2])))
# Verify that the implementation is not using == on the sets directly.
asserts.true(env, sets.is_equal(depset([1]), depset([1])))
# Verify that the implementation is not using == on the sets directly.
asserts.true(env, sets.is_equal(depset([1]), depset([1])))
# If passing a list, verify that duplicate elements are ignored.
asserts.true(env, sets.is_equal([1, 1], [1]))
# If passing a list, verify that duplicate elements are ignored.
asserts.true(env, sets.is_equal([1, 1], [1]))
unittest.end(env)
unittest.end(env)
is_equal_test = unittest.make(_is_equal_test)
def _is_subset_test(ctx):
"""Unit tests for sets.is_subset."""
env = unittest.begin(ctx)
"""Unit tests for sets.is_subset."""
env = unittest.begin(ctx)
asserts.true(env, sets.is_subset([], []))
asserts.true(env, sets.is_subset([], [1]))
asserts.false(env, sets.is_subset([1], []))
asserts.true(env, sets.is_subset([1], [1]))
asserts.true(env, sets.is_subset([1], [1, 2]))
asserts.false(env, sets.is_subset([1], [2]))
asserts.true(env, sets.is_subset([1], depset([1, 2])))
asserts.true(env, sets.is_subset([], []))
asserts.true(env, sets.is_subset([], [1]))
asserts.false(env, sets.is_subset([1], []))
asserts.true(env, sets.is_subset([1], [1]))
asserts.true(env, sets.is_subset([1], [1, 2]))
asserts.false(env, sets.is_subset([1], [2]))
asserts.true(env, sets.is_subset([1], depset([1, 2])))
# If passing a list, verify that duplicate elements are ignored.
asserts.true(env, sets.is_subset([1, 1], [1, 2]))
# If passing a list, verify that duplicate elements are ignored.
asserts.true(env, sets.is_subset([1, 1], [1, 2]))
unittest.end(env)
unittest.end(env)
is_subset_test = unittest.make(_is_subset_test)
def _disjoint_test(ctx):
"""Unit tests for sets.disjoint."""
env = unittest.begin(ctx)
"""Unit tests for sets.disjoint."""
env = unittest.begin(ctx)
asserts.true(env, sets.disjoint([], []))
asserts.true(env, sets.disjoint([], [1]))
asserts.true(env, sets.disjoint([1], []))
asserts.false(env, sets.disjoint([1], [1]))
asserts.false(env, sets.disjoint([1], [1, 2]))
asserts.true(env, sets.disjoint([1], [2]))
asserts.true(env, sets.disjoint([1], depset([2])))
asserts.true(env, sets.disjoint([], []))
asserts.true(env, sets.disjoint([], [1]))
asserts.true(env, sets.disjoint([1], []))
asserts.false(env, sets.disjoint([1], [1]))
asserts.false(env, sets.disjoint([1], [1, 2]))
asserts.true(env, sets.disjoint([1], [2]))
asserts.true(env, sets.disjoint([1], depset([2])))
# If passing a list, verify that duplicate elements are ignored.
asserts.false(env, sets.disjoint([1, 1], [1, 2]))
# If passing a list, verify that duplicate elements are ignored.
asserts.false(env, sets.disjoint([1, 1], [1, 2]))
unittest.end(env)
unittest.end(env)
disjoint_test = unittest.make(_disjoint_test)
def _intersection_test(ctx):
"""Unit tests for sets.intersection."""
env = unittest.begin(ctx)
"""Unit tests for sets.intersection."""
env = unittest.begin(ctx)
asserts.set_equals(env, [], sets.intersection([], []))
asserts.set_equals(env, [], sets.intersection([], [1]))
asserts.set_equals(env, [], sets.intersection([1], []))
asserts.set_equals(env, [1], sets.intersection([1], [1]))
asserts.set_equals(env, [1], sets.intersection([1], [1, 2]))
asserts.set_equals(env, [], sets.intersection([1], [2]))
asserts.set_equals(env, [1], sets.intersection([1], depset([1])))
asserts.set_equals(env, [], sets.intersection([], []))
asserts.set_equals(env, [], sets.intersection([], [1]))
asserts.set_equals(env, [], sets.intersection([1], []))
asserts.set_equals(env, [1], sets.intersection([1], [1]))
asserts.set_equals(env, [1], sets.intersection([1], [1, 2]))
asserts.set_equals(env, [], sets.intersection([1], [2]))
asserts.set_equals(env, [1], sets.intersection([1], depset([1])))
# If passing a list, verify that duplicate elements are ignored.
asserts.set_equals(env, [1], sets.intersection([1, 1], [1, 2]))
# If passing a list, verify that duplicate elements are ignored.
asserts.set_equals(env, [1], sets.intersection([1, 1], [1, 2]))
unittest.end(env)
unittest.end(env)
intersection_test = unittest.make(_intersection_test)
def _union_test(ctx):
"""Unit tests for sets.union."""
env = unittest.begin(ctx)
"""Unit tests for sets.union."""
env = unittest.begin(ctx)
asserts.set_equals(env, [], sets.union())
asserts.set_equals(env, [1], sets.union([1]))
asserts.set_equals(env, [], sets.union([], []))
asserts.set_equals(env, [1], sets.union([], [1]))
asserts.set_equals(env, [1], sets.union([1], []))
asserts.set_equals(env, [1], sets.union([1], [1]))
asserts.set_equals(env, [1, 2], sets.union([1], [1, 2]))
asserts.set_equals(env, [1, 2], sets.union([1], [2]))
asserts.set_equals(env, [1], sets.union([1], depset([1])))
asserts.set_equals(env, [], sets.union())
asserts.set_equals(env, [1], sets.union([1]))
asserts.set_equals(env, [], sets.union([], []))
asserts.set_equals(env, [1], sets.union([], [1]))
asserts.set_equals(env, [1], sets.union([1], []))
asserts.set_equals(env, [1], sets.union([1], [1]))
asserts.set_equals(env, [1, 2], sets.union([1], [1, 2]))
asserts.set_equals(env, [1, 2], sets.union([1], [2]))
asserts.set_equals(env, [1], sets.union([1], depset([1])))
# If passing a list, verify that duplicate elements are ignored.
asserts.set_equals(env, [1, 2], sets.union([1, 1], [1, 2]))
# If passing a list, verify that duplicate elements are ignored.
asserts.set_equals(env, [1, 2], sets.union([1, 1], [1, 2]))
unittest.end(env)
unittest.end(env)
union_test = unittest.make(_union_test)
def _difference_test(ctx):
"""Unit tests for sets.difference."""
env = unittest.begin(ctx)
"""Unit tests for sets.difference."""
env = unittest.begin(ctx)
asserts.set_equals(env, [], sets.difference([], []))
asserts.set_equals(env, [], sets.difference([], [1]))
asserts.set_equals(env, [1], sets.difference([1], []))
asserts.set_equals(env, [], sets.difference([1], [1]))
asserts.set_equals(env, [], sets.difference([1], [1, 2]))
asserts.set_equals(env, [1], sets.difference([1], [2]))
asserts.set_equals(env, [], sets.difference([1], depset([1])))
asserts.set_equals(env, [], sets.difference([], []))
asserts.set_equals(env, [], sets.difference([], [1]))
asserts.set_equals(env, [1], sets.difference([1], []))
asserts.set_equals(env, [], sets.difference([1], [1]))
asserts.set_equals(env, [], sets.difference([1], [1, 2]))
asserts.set_equals(env, [1], sets.difference([1], [2]))
asserts.set_equals(env, [], sets.difference([1], depset([1])))
# If passing a list, verify that duplicate elements are ignored.
asserts.set_equals(env, [2], sets.difference([1, 2], [1, 1]))
# If passing a list, verify that duplicate elements are ignored.
asserts.set_equals(env, [2], sets.difference([1, 2], [1, 1]))
unittest.end(env)
unittest.end(env)
difference_test = unittest.make(_difference_test)
def sets_test_suite():
"""Creates the test targets and test suite for sets.bzl tests."""
unittest.suite(
"sets_tests",
disjoint_test,
intersection_test,
is_equal_test,
is_subset_test,
difference_test,
union_test,
)
"""Creates the test targets and test suite for sets.bzl tests."""
unittest.suite(
"sets_tests",
disjoint_test,
intersection_test,
is_equal_test,
is_subset_test,
difference_test,
union_test,
)

View File

@ -14,98 +14,94 @@
"""Unit tests for shell.bzl."""
load("//:lib.bzl", "shell", "asserts", "unittest")
load("//:lib.bzl", "asserts", "shell", "unittest")
def _shell_array_literal_test(ctx):
"""Unit tests for shell.array_literal."""
env = unittest.begin(ctx)
"""Unit tests for shell.array_literal."""
env = unittest.begin(ctx)
asserts.equals(env, "()", shell.array_literal([]))
asserts.equals(env, "('1')", shell.array_literal([1]))
asserts.equals(env, "('1' '2' '3')", shell.array_literal([1, 2, 3]))
asserts.equals(env, "('$foo')", shell.array_literal(["$foo"]))
asserts.equals(env, "('qu\"o\"te')", shell.array_literal(['qu"o"te']))
asserts.equals(env, "()", shell.array_literal([]))
asserts.equals(env, "('1')", shell.array_literal([1]))
asserts.equals(env, "('1' '2' '3')", shell.array_literal([1, 2, 3]))
asserts.equals(env, "('$foo')", shell.array_literal(["$foo"]))
asserts.equals(env, "('qu\"o\"te')", shell.array_literal(['qu"o"te']))
unittest.end(env)
unittest.end(env)
shell_array_literal_test = unittest.make(_shell_array_literal_test)
def _shell_quote_test(ctx):
"""Unit tests for shell.quote."""
env = unittest.begin(ctx)
"""Unit tests for shell.quote."""
env = unittest.begin(ctx)
asserts.equals(env, "'foo'", shell.quote("foo"))
asserts.equals(env, "'foo bar'", shell.quote("foo bar"))
asserts.equals(env, "'three spaces'", shell.quote("three spaces"))
asserts.equals(env, "' leading'", shell.quote(" leading"))
asserts.equals(env, "'trailing '", shell.quote("trailing "))
asserts.equals(env, "'new\nline'", shell.quote("new\nline"))
asserts.equals(env, "'tab\tcharacter'", shell.quote("tab\tcharacter"))
asserts.equals(env, "'$foo'", shell.quote("$foo"))
asserts.equals(env, "'qu\"o\"te'", shell.quote('qu"o"te'))
asserts.equals(env, "'it'\\''s'", shell.quote("it's"))
asserts.equals(env, "'foo\\bar'", shell.quote(r"foo\bar"))
asserts.equals(env, "'back`echo q`uote'", shell.quote(r"back`echo q`uote"))
asserts.equals(env, "'foo'", shell.quote("foo"))
asserts.equals(env, "'foo bar'", shell.quote("foo bar"))
asserts.equals(env, "'three spaces'", shell.quote("three spaces"))
asserts.equals(env, "' leading'", shell.quote(" leading"))
asserts.equals(env, "'trailing '", shell.quote("trailing "))
asserts.equals(env, "'new\nline'", shell.quote("new\nline"))
asserts.equals(env, "'tab\tcharacter'", shell.quote("tab\tcharacter"))
asserts.equals(env, "'$foo'", shell.quote("$foo"))
asserts.equals(env, "'qu\"o\"te'", shell.quote('qu"o"te'))
asserts.equals(env, "'it'\\''s'", shell.quote("it's"))
asserts.equals(env, "'foo\\bar'", shell.quote("foo\\bar"))
asserts.equals(env, "'back`echo q`uote'", shell.quote("back`echo q`uote"))
unittest.end(env)
unittest.end(env)
shell_quote_test = unittest.make(_shell_quote_test)
def _shell_spawn_e2e_test_impl(ctx):
"""Test spawning a real shell."""
args = [
"foo",
"foo bar",
"three spaces",
" leading",
"trailing ",
"new\nline",
"tab\tcharacter",
"$foo",
'qu"o"te',
"it's",
r"foo\bar",
"back`echo q`uote",
]
script_content = "\n".join([
"#!/bin/bash",
"myarray=" + shell.array_literal(args),
'output=$(echo "${myarray[@]}")',
# For logging:
'echo "DEBUG: output=[${output}]" >&2',
# The following is a shell representation of what the echo of the quoted
# array will look like. It looks a bit confusing considering it's shell
# quoted into Python. Shell using single quotes to minimize shell
# escaping, so only the single quote needs to be escaped as '\'', all
# others are essentially kept literally.
"expected='foo foo bar three spaces leading trailing new",
"line tab\tcharacter $foo qu\"o\"te it'\\''s foo\\bar back`echo q`uote'",
'[[ "${output}" == "${expected}" ]]',
])
script_file = ctx.actions.declare_file("%s.sh" % (ctx.label.name))
ctx.actions.write(
output = script_file,
content = script_content,
is_executable = True,
)
return [
DefaultInfo(executable=script_file),
]
"""Test spawning a real shell."""
args = [
"foo",
"foo bar",
"three spaces",
" leading",
"trailing ",
"new\nline",
"tab\tcharacter",
"$foo",
'qu"o"te',
"it's",
"foo\\bar",
"back`echo q`uote",
]
script_content = "\n".join([
"#!/bin/bash",
"myarray=" + shell.array_literal(args),
'output=$(echo "${myarray[@]}")',
# For logging:
'echo "DEBUG: output=[${output}]" >&2',
# The following is a shell representation of what the echo of the quoted
# array will look like. It looks a bit confusing considering it's shell
# quoted into Python. Shell using single quotes to minimize shell
# escaping, so only the single quote needs to be escaped as '\'', all
# others are essentially kept literally.
"expected='foo foo bar three spaces leading trailing new",
"line tab\tcharacter $foo qu\"o\"te it'\\''s foo\\bar back`echo q`uote'",
'[[ "${output}" == "${expected}" ]]',
])
script_file = ctx.actions.declare_file("%s.sh" % (ctx.label.name))
ctx.actions.write(
output = script_file,
content = script_content,
is_executable = True,
)
return [
DefaultInfo(executable = script_file),
]
shell_spawn_e2e_test = rule(
test = True,
implementation = _shell_spawn_e2e_test_impl,
)
def shell_test_suite():
"""Creates the test targets and test suite for shell.bzl tests."""
unittest.suite(
"shell_tests",
shell_array_literal_test,
shell_quote_test,
shell_spawn_e2e_test,
)
"""Creates the test targets and test suite for shell.bzl tests."""
unittest.suite(
"shell_tests",
shell_array_literal_test,
shell_quote_test,
shell_spawn_e2e_test,
)

View File

@ -14,36 +14,40 @@
"""Unit tests for structs.bzl."""
load("//:lib.bzl", "structs", "asserts", "unittest")
load("//:lib.bzl", "asserts", "structs", "unittest")
def _add_test(ctx):
"""Unit tests for dicts.add."""
env = unittest.begin(ctx)
"""Unit tests for dicts.add."""
env = unittest.begin(ctx)
# Test zero- and one-argument behavior.
asserts.equals(env, {}, structs.to_dict(struct()))
asserts.equals(env, {"a": 1}, structs.to_dict(struct(a=1)))
# Test zero- and one-argument behavior.
asserts.equals(env, {}, structs.to_dict(struct()))
asserts.equals(env, {"a": 1}, structs.to_dict(struct(a = 1)))
# Test simple two-argument behavior.
asserts.equals(env, {"a": 1, "b": 2}, structs.to_dict(struct(a=1, b=2)))
# Test simple two-argument behavior.
asserts.equals(env, {"a": 1, "b": 2}, structs.to_dict(struct(a = 1, b = 2)))
# Test simple more-than-two-argument behavior.
asserts.equals(env, {"a": 1, "b": 2, "c": 3, "d": 4},
structs.to_dict(struct(a=1, b=2, c=3, d=4)))
# Test simple more-than-two-argument behavior.
asserts.equals(
env,
{"a": 1, "b": 2, "c": 3, "d": 4},
structs.to_dict(struct(a = 1, b = 2, c = 3, d = 4)),
)
# Test transformation is not applied transitively.
asserts.equals(env, {"a": 1, "b": struct(bb=1)},
structs.to_dict(struct(a=1, b=struct(bb=1))))
# Test transformation is not applied transitively.
asserts.equals(
env,
{"a": 1, "b": struct(bb = 1)},
structs.to_dict(struct(a = 1, b = struct(bb = 1))),
)
unittest.end(env)
unittest.end(env)
add_test = unittest.make(_add_test)
def structs_test_suite():
"""Creates the test targets and test suite for structs.bzl tests."""
unittest.suite(
"structs_tests",
add_test,
)
"""Creates the test targets and test suite for structs.bzl tests."""
unittest.suite(
"structs_tests",
add_test,
)

View File

@ -13,14 +13,12 @@
# limitations under the License.
"""Unit tests for types.bzl."""
load("//:lib.bzl", "types", "asserts", "unittest")
load("//:lib.bzl", "asserts", "types", "unittest")
def _a_function():
"""A dummy function for testing."""
pass
def _is_string_test(ctx):
"""Unit tests for types.is_string."""
@ -39,10 +37,8 @@ def _is_string_test(ctx):
unittest.end(env)
is_string_test = unittest.make(_is_string_test)
def _is_bool_test(ctx):
"""Unit tests for types.is_bool."""
@ -61,10 +57,8 @@ def _is_bool_test(ctx):
unittest.end(env)
is_bool_test = unittest.make(_is_bool_test)
def _is_list_test(ctx):
"""Unit tests for types.is_list."""
@ -83,10 +77,8 @@ def _is_list_test(ctx):
unittest.end(env)
is_list_test = unittest.make(_is_list_test)
def _is_none_test(ctx):
"""Unit tests for types.is_none."""
@ -105,10 +97,8 @@ def _is_none_test(ctx):
unittest.end(env)
is_none_test = unittest.make(_is_none_test)
def _is_int_test(ctx):
"""Unit tests for types.is_int."""
@ -128,17 +118,15 @@ def _is_int_test(ctx):
unittest.end(env)
is_int_test = unittest.make(_is_int_test)
def _is_tuple_test(ctx):
"""Unit tests for types.is_tuple."""
env = unittest.begin(ctx)
asserts.true(env, types.is_tuple(()))
asserts.true(env, types.is_tuple((1, )))
asserts.true(env, types.is_tuple((1,)))
asserts.false(env, types.is_tuple(1))
asserts.false(env, types.is_tuple("s"))
@ -151,17 +139,15 @@ def _is_tuple_test(ctx):
unittest.end(env)
is_tuple_test = unittest.make(_is_tuple_test)
def _is_dict_test(ctx):
"""Unit tests for types.is_dict."""
env = unittest.begin(ctx)
asserts.true(env, types.is_dict({}))
asserts.true(env, types.is_dict({'key': 'value'}))
asserts.true(env, types.is_dict({"key": "value"}))
asserts.false(env, types.is_dict(1))
asserts.false(env, types.is_dict("s"))
@ -174,10 +160,8 @@ def _is_dict_test(ctx):
unittest.end(env)
is_dict_test = unittest.make(_is_dict_test)
def _is_function_test(ctx):
"""Unit tests for types.is_dict."""
@ -196,10 +180,8 @@ def _is_function_test(ctx):
unittest.end(env)
is_function_test = unittest.make(_is_function_test)
def types_test_suite():
"""Creates the test targets and test suite for types.bzl tests."""
unittest.suite(

View File

@ -14,55 +14,55 @@
"""Unit tests for versions.bzl."""
load("//:lib.bzl", "versions", "asserts", "unittest")
load("//:lib.bzl", "asserts", "unittest", "versions")
def _parse_test(ctx):
"""Unit tests for versions.parse"""
env = unittest.begin(ctx)
"""Unit tests for versions.parse"""
env = unittest.begin(ctx)
asserts.equals(env, (0, 10, 0), versions.parse("0.10.0rc1 abcd123"))
asserts.equals(env, (0, 4, 0), versions.parse("0.4.0 abcd123"))
asserts.equals(env, (0, 4, 0), versions.parse("0.4.0"))
asserts.equals(env, (0, 4, 0), versions.parse("0.4.0rc"))
asserts.equals(env, (0, 10, 0), versions.parse("0.10.0rc1 abcd123"))
asserts.equals(env, (0, 4, 0), versions.parse("0.4.0 abcd123"))
asserts.equals(env, (0, 4, 0), versions.parse("0.4.0"))
asserts.equals(env, (0, 4, 0), versions.parse("0.4.0rc"))
unittest.end(env)
unittest.end(env)
def _version_comparison_test(ctx):
"""Unit tests for versions.is_at_least and is_at_most"""
env = unittest.begin(ctx)
"""Unit tests for versions.is_at_least and is_at_most"""
env = unittest.begin(ctx)
asserts.false(env, versions.is_at_least("0.11.0 123abcd", "0.10.0rc1 abcd123"))
asserts.true(env, versions.is_at_least("0.9.0", "0.10.0rc2"))
asserts.true(env, versions.is_at_least("0.9.0", "0.9.0rc3"))
asserts.true(env, versions.is_at_least("0.9.0", "1.2.3"))
asserts.false(env, versions.is_at_least("0.11.0 123abcd", "0.10.0rc1 abcd123"))
asserts.true(env, versions.is_at_least("0.9.0", "0.10.0rc2"))
asserts.true(env, versions.is_at_least("0.9.0", "0.9.0rc3"))
asserts.true(env, versions.is_at_least("0.9.0", "1.2.3"))
asserts.false(env, versions.is_at_most("0.4.0 123abcd", "0.10.0rc1 abcd123"))
asserts.true(env, versions.is_at_most("0.4.0", "0.3.0rc2"))
asserts.true(env, versions.is_at_most("0.4.0", "0.4.0rc3"))
asserts.true(env, versions.is_at_most("1.4.0", "0.4.0rc3"))
asserts.false(env, versions.is_at_most("0.4.0 123abcd", "0.10.0rc1 abcd123"))
asserts.true(env, versions.is_at_most("0.4.0", "0.3.0rc2"))
asserts.true(env, versions.is_at_most("0.4.0", "0.4.0rc3"))
asserts.true(env, versions.is_at_most("1.4.0", "0.4.0rc3"))
unittest.end(env)
unittest.end(env)
def _check_test(ctx):
"""Unit tests for versions.check"""
env = unittest.begin(ctx)
"""Unit tests for versions.check"""
env = unittest.begin(ctx)
asserts.equals(env, None, versions.check("0.4.5 abcdef", bazel_version="0.10.0rc1 abcd123"))
asserts.equals(env, None, versions.check("0.4.5", bazel_version="0.4.5"))
asserts.equals(env, None, versions.check("0.4.5", bazel_version="0.10.0rc1 abcd123"))
asserts.equals(env, None, versions.check("0.4.5", maximum_bazel_version="1.0.0", bazel_version="0.10.0rc1 abcd123"))
asserts.equals(env, None, versions.check("0.4.5 abcdef", bazel_version = "0.10.0rc1 abcd123"))
asserts.equals(env, None, versions.check("0.4.5", bazel_version = "0.4.5"))
asserts.equals(env, None, versions.check("0.4.5", bazel_version = "0.10.0rc1 abcd123"))
asserts.equals(env, None, versions.check("0.4.5", maximum_bazel_version = "1.0.0", bazel_version = "0.10.0rc1 abcd123"))
unittest.end(env)
unittest.end(env)
parse_test = unittest.make(_parse_test)
version_comparison_test = unittest.make(_version_comparison_test)
check_test = unittest.make(_check_test)
def versions_test_suite():
"""Creates the test targets and test suite for versions.bzl tests."""
unittest.suite(
"versions_tests",
parse_test,
version_comparison_test,
check_test,
)
"""Creates the test targets and test suite for versions.bzl tests."""
unittest.suite(
"versions_tests",
parse_test,
version_comparison_test,
check_test,
)