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:
parent
a5431b7bab
commit
e5203c0f5d
|
@ -26,9 +26,14 @@ fi
|
||||||
# Asked to do a buildifier run.
|
# Asked to do a buildifier run.
|
||||||
if [[ -n "${BUILDIFER:-}" ]]; then
|
if [[ -n "${BUILDIFER:-}" ]]; then
|
||||||
# bazelbuild/buildtools/issues/220 - diff doesn't include the file that needs updating
|
# 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
|
if ! find . \( -name BUILD -o -name "*.bzl" \) -print | xargs buildifier -d > /dev/null 2>&1 ; then
|
||||||
echo "ERROR: BUILD file formatting issue(s)"
|
echo "ERROR: BUILD/.bzl file formatting issue(s):"
|
||||||
find . -name BUILD -print -exec buildifier -v -d {} \;
|
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
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
25
lib.bzl
25
lib.bzl
|
@ -14,22 +14,21 @@
|
||||||
|
|
||||||
"""Index from which multiple modules can be loaded."""
|
"""Index from which multiple modules can be loaded."""
|
||||||
|
|
||||||
load("//lib:collections.bzl", _collections="collections")
|
load("//lib:collections.bzl", _collections = "collections")
|
||||||
load("//lib:dicts.bzl", _dicts="dicts")
|
load("//lib:dicts.bzl", _dicts = "dicts")
|
||||||
load("//lib:new_sets.bzl", _new_sets="sets")
|
load("//lib:new_sets.bzl", _new_sets = "sets")
|
||||||
load("//lib:partial.bzl", _partial="partial")
|
load("//lib:partial.bzl", _partial = "partial")
|
||||||
load("//lib:paths.bzl", _paths="paths")
|
load("//lib:paths.bzl", _paths = "paths")
|
||||||
load("//lib:selects.bzl", _selects="selects")
|
load("//lib:selects.bzl", _selects = "selects")
|
||||||
load("//lib:sets.bzl", _sets="sets")
|
load("//lib:sets.bzl", _sets = "sets")
|
||||||
load("//lib:shell.bzl", _shell="shell")
|
load("//lib:shell.bzl", _shell = "shell")
|
||||||
load("//lib:structs.bzl", _structs="structs")
|
load("//lib:structs.bzl", _structs = "structs")
|
||||||
load("//lib:types.bzl", _types="types")
|
load("//lib:types.bzl", _types = "types")
|
||||||
load("//lib:versions.bzl", _versions="versions")
|
load("//lib:versions.bzl", _versions = "versions")
|
||||||
|
|
||||||
# The unittest module is treated differently to give more convenient names to
|
# The unittest module is treated differently to give more convenient names to
|
||||||
# the assert functions, while keeping them in the same .bzl file.
|
# 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
|
collections = _collections
|
||||||
dicts = _dicts
|
dicts = _dicts
|
||||||
|
|
|
@ -14,60 +14,56 @@
|
||||||
|
|
||||||
"""Skylib module containing functions that operate on collections."""
|
"""Skylib module containing functions that operate on collections."""
|
||||||
|
|
||||||
|
|
||||||
def _after_each(separator, iterable):
|
def _after_each(separator, iterable):
|
||||||
"""Inserts `separator` after each item in `iterable`.
|
"""Inserts `separator` after each item in `iterable`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
separator: The value to insert after each item in `iterable`.
|
separator: The value to insert after each item in `iterable`.
|
||||||
iterable: The list into which to intersperse the separator.
|
iterable: The list into which to intersperse the separator.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A new list with `separator` after each item in `iterable`.
|
A new list with `separator` after each item in `iterable`.
|
||||||
"""
|
"""
|
||||||
result = []
|
result = []
|
||||||
for x in iterable:
|
for x in iterable:
|
||||||
result.append(x)
|
result.append(x)
|
||||||
result.append(separator)
|
result.append(separator)
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
def _before_each(separator, iterable):
|
def _before_each(separator, iterable):
|
||||||
"""Inserts `separator` before each item in `iterable`.
|
"""Inserts `separator` before each item in `iterable`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
separator: The value to insert before each item in `iterable`.
|
separator: The value to insert before each item in `iterable`.
|
||||||
iterable: The list into which to intersperse the separator.
|
iterable: The list into which to intersperse the separator.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A new list with `separator` before each item in `iterable`.
|
A new list with `separator` before each item in `iterable`.
|
||||||
"""
|
"""
|
||||||
result = []
|
result = []
|
||||||
for x in iterable:
|
for x in iterable:
|
||||||
result.append(separator)
|
result.append(separator)
|
||||||
result.append(x)
|
result.append(x)
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
def _uniq(iterable):
|
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:
|
Args:
|
||||||
iterable: An iterable to filter.
|
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()
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A new list with all unique elements from `iterable`.
|
||||||
|
"""
|
||||||
|
unique_elements = {element: None for element in iterable}
|
||||||
|
return unique_elements.keys()
|
||||||
|
|
||||||
collections = struct(
|
collections = struct(
|
||||||
after_each=_after_each,
|
after_each = _after_each,
|
||||||
before_each=_before_each,
|
before_each = _before_each,
|
||||||
uniq=_uniq,
|
uniq = _uniq,
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,30 +14,28 @@
|
||||||
|
|
||||||
"""Skylib module containing functions that operate on dictionaries."""
|
"""Skylib module containing functions that operate on dictionaries."""
|
||||||
|
|
||||||
|
|
||||||
def _add(*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
|
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.
|
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
|
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
|
dictionaries, so that it follows arithmetic identities and callers can avoid
|
||||||
special cases for their inputs: the sum of zero dictionaries is the empty
|
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.
|
dictionary, and the sum of a single dictionary is a copy of itself.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
*dictionaries: Zero or more dictionaries to be added.
|
*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
|
|
||||||
|
|
||||||
|
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(
|
dicts = struct(
|
||||||
add=_add,
|
add = _add,
|
||||||
)
|
)
|
||||||
|
|
309
lib/new_sets.bzl
309
lib/new_sets.bzl
|
@ -22,230 +22,215 @@
|
||||||
|
|
||||||
load(":dicts.bzl", "dicts")
|
load(":dicts.bzl", "dicts")
|
||||||
|
|
||||||
|
def _make(elements = None):
|
||||||
|
"""Creates a new set.
|
||||||
|
|
||||||
def _make(elements=None):
|
All elements must be hashable.
|
||||||
"""Creates a new set.
|
|
||||||
|
|
||||||
All elements must be hashable.
|
Args:
|
||||||
|
elements: Optional sequence to construct the set out of.
|
||||||
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})
|
|
||||||
|
|
||||||
|
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):
|
def _copy(s):
|
||||||
"""Creates a new set from another set.
|
"""Creates a new set from another set.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
s: A set, as returned by `sets.make()`.
|
s: A set, as returned by `sets.make()`.
|
||||||
|
|
||||||
Returns:
|
|
||||||
A new set containing the same elements as `s`.
|
|
||||||
"""
|
|
||||||
return struct(_values = dict(s._values))
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A new set containing the same elements as `s`.
|
||||||
|
"""
|
||||||
|
return struct(_values = dict(s._values))
|
||||||
|
|
||||||
def _to_list(s):
|
def _to_list(s):
|
||||||
"""Creates a list from the values in the set.
|
"""Creates a list from the values in the set.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
s: A set, as returned by `sets.make()`.
|
s: A set, as returned by `sets.make()`.
|
||||||
|
|
||||||
Returns:
|
|
||||||
A list of values inserted into the set.
|
|
||||||
"""
|
|
||||||
return s._values.keys()
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A list of values inserted into the set.
|
||||||
|
"""
|
||||||
|
return s._values.keys()
|
||||||
|
|
||||||
def _insert(s, e):
|
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:
|
Args:
|
||||||
s: A set, as returned by `sets.make()`.
|
s: A set, as returned by `sets.make()`.
|
||||||
e: The element to be inserted.
|
e: The element to be inserted.
|
||||||
|
|
||||||
Returns:
|
|
||||||
The set `s` with `e` included.
|
|
||||||
"""
|
|
||||||
s._values[e] = None
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The set `s` with `e` included.
|
||||||
|
"""
|
||||||
|
s._values[e] = None
|
||||||
|
return s
|
||||||
|
|
||||||
def _remove(s, e):
|
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:
|
Args:
|
||||||
s: A set, as returned by `sets.make()`.
|
s: A set, as returned by `sets.make()`.
|
||||||
e: The element to be removed.
|
e: The element to be removed.
|
||||||
|
|
||||||
Returns:
|
|
||||||
The set `s` with `e` removed.
|
|
||||||
"""
|
|
||||||
s._values.pop(e)
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The set `s` with `e` removed.
|
||||||
|
"""
|
||||||
|
s._values.pop(e)
|
||||||
|
return s
|
||||||
|
|
||||||
def _contains(a, e):
|
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:
|
Args:
|
||||||
a: A set, as returned by `sets.make()`.
|
a: A set, as returned by `sets.make()`.
|
||||||
e: The element to look for.
|
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
|
|
||||||
|
|
||||||
|
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):
|
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:
|
Args:
|
||||||
a: A set, as returned by `sets.make()`.
|
a: A set, as returned by `sets.make()`.
|
||||||
b: 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
|
|
||||||
|
|
||||||
|
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):
|
def _is_equal(a, b):
|
||||||
"""Returns whether two sets are equal.
|
"""Returns whether two sets are equal.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
a: A set, as returned by `sets.make()`.
|
a: A set, as returned by `sets.make()`.
|
||||||
b: 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
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if `a` is equal to `b`, False otherwise.
|
||||||
|
"""
|
||||||
|
return a._values == b._values
|
||||||
|
|
||||||
def _is_subset(a, b):
|
def _is_subset(a, b):
|
||||||
"""Returns whether `a` is a subset of `b`.
|
"""Returns whether `a` is a subset of `b`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
a: A set, as returned by `sets.make()`.
|
a: A set, as returned by `sets.make()`.
|
||||||
b: 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
|
|
||||||
|
|
||||||
|
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):
|
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:
|
Args:
|
||||||
a: A set, as returned by `sets.make()`.
|
a: A set, as returned by `sets.make()`.
|
||||||
b: 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
|
|
||||||
|
|
||||||
|
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):
|
def _intersection(a, b):
|
||||||
"""Returns the intersection of two sets.
|
"""Returns the intersection of two sets.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
a: A set, as returned by `sets.make()`.
|
a: A set, as returned by `sets.make()`.
|
||||||
b: 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})
|
|
||||||
|
|
||||||
|
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):
|
def _union(*args):
|
||||||
"""Returns the union of several sets.
|
"""Returns the union of several sets.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
*args: An arbitrary number of sets or lists.
|
*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]))
|
|
||||||
|
|
||||||
|
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):
|
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:
|
Args:
|
||||||
a: A set, as returned by `sets.make()`.
|
a: A set, as returned by `sets.make()`.
|
||||||
b: 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})
|
|
||||||
|
|
||||||
|
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):
|
def _length(s):
|
||||||
"""Returns the number of elements in a set.
|
"""Returns the number of elements in a set.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
s: A set, as returned by `sets.make()`.
|
s: A set, as returned by `sets.make()`.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
An integer representing the number of elements in the set.
|
An integer representing the number of elements in the set.
|
||||||
"""
|
"""
|
||||||
return len(s._values)
|
return len(s._values)
|
||||||
|
|
||||||
def _repr(s):
|
def _repr(s):
|
||||||
"""Returns a string value representing the set.
|
"""Returns a string value representing the set.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
s: A set, as returned by `sets.make()`.
|
s: A set, as returned by `sets.make()`.
|
||||||
|
|
||||||
Returns:
|
|
||||||
A string representing the set.
|
|
||||||
"""
|
|
||||||
return repr(s._values.keys())
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A string representing the set.
|
||||||
|
"""
|
||||||
|
return repr(s._values.keys())
|
||||||
|
|
||||||
sets = struct(
|
sets = struct(
|
||||||
make = _make,
|
make = _make,
|
||||||
copy = _copy,
|
copy = _copy,
|
||||||
to_list = _to_list,
|
to_list = _to_list,
|
||||||
insert = _insert,
|
insert = _insert,
|
||||||
contains = _contains,
|
contains = _contains,
|
||||||
is_equal = _is_equal,
|
is_equal = _is_equal,
|
||||||
is_subset = _is_subset,
|
is_subset = _is_subset,
|
||||||
disjoint = _disjoint,
|
disjoint = _disjoint,
|
||||||
intersection = _intersection,
|
intersection = _intersection,
|
||||||
union = _union,
|
union = _union,
|
||||||
difference = _difference,
|
difference = _difference,
|
||||||
length = _length,
|
length = _length,
|
||||||
remove = _remove,
|
remove = _remove,
|
||||||
repr = _repr,
|
repr = _repr,
|
||||||
str = _repr,
|
str = _repr,
|
||||||
)
|
)
|
||||||
|
|
156
lib/partial.bzl
156
lib/partial.bzl
|
@ -20,111 +20,111 @@ Similar to https://docs.python.org/3/library/functools.html#functools.partial.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _call(partial, *args, **kwargs):
|
def _call(partial, *args, **kwargs):
|
||||||
"""Calls a partial created using `make`.
|
"""Calls a partial created using `make`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
partial: The partial to be called.
|
partial: The partial to be called.
|
||||||
*args: Additional positional arguments to be appended to the ones given to
|
*args: Additional positional arguments to be appended to the ones given to
|
||||||
make.
|
make.
|
||||||
**kwargs: Additional keyword arguments to augment and override the ones
|
**kwargs: Additional keyword arguments to augment and override the ones
|
||||||
given to make.
|
given to make.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Whatever the function in the partial returns.
|
Whatever the function in the partial returns.
|
||||||
"""
|
"""
|
||||||
function_args = partial.args + args
|
function_args = partial.args + args
|
||||||
function_kwargs = dict(partial.kwargs)
|
function_kwargs = dict(partial.kwargs)
|
||||||
function_kwargs.update(kwargs)
|
function_kwargs.update(kwargs)
|
||||||
return partial.function(*function_args, **function_kwargs)
|
return partial.function(*function_args, **function_kwargs)
|
||||||
|
|
||||||
def _make(func, *args, **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
|
A partial can have args assigned to it at the make site, and can have args
|
||||||
passed to it at the call sites.
|
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
|
# function with no args
|
||||||
def function1():
|
def function1():
|
||||||
...
|
...
|
||||||
|
|
||||||
# function with 2 args
|
# function with 2 args
|
||||||
def function2(arg1, arg2):
|
def function2(arg1, arg2):
|
||||||
...
|
...
|
||||||
|
|
||||||
# function with 2 args and keyword args
|
# function with 2 args and keyword args
|
||||||
def function3(arg1, arg2, x, y):
|
def function3(arg1, arg2, x, y):
|
||||||
...
|
...
|
||||||
|
|
||||||
The positional args passed to the function are the args passed into make
|
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
|
followed by any additional positional args given to call. The below example
|
||||||
illustrates a function with two positional arguments where one is supplied by
|
illustrates a function with two positional arguments where one is supplied by
|
||||||
make and the other by call:
|
make and the other by call:
|
||||||
|
|
||||||
# function demonstrating 1 arg at make site, and 1 arg at call site
|
# function demonstrating 1 arg at make site, and 1 arg at call site
|
||||||
def _foo(make_arg1, func_arg1):
|
def _foo(make_arg1, func_arg1):
|
||||||
print(make_arg1 + " " + func_arg1 + "!")
|
print(make_arg1 + " " + func_arg1 + "!")
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
hi_func = partial.make(_foo, "Hello")
|
hi_func = partial.make(_foo, "Hello")
|
||||||
bye_func = partial.make(_foo, "Goodbye")
|
bye_func = partial.make(_foo, "Goodbye")
|
||||||
partial.call(hi_func, "Jennifer")
|
partial.call(hi_func, "Jennifer")
|
||||||
partial.call(hi_func, "Dave")
|
partial.call(hi_func, "Dave")
|
||||||
partial.call(bye_func, "Jennifer")
|
partial.call(bye_func, "Jennifer")
|
||||||
partial.call(bye_func, "Dave")
|
partial.call(bye_func, "Dave")
|
||||||
|
|
||||||
prints:
|
prints:
|
||||||
|
|
||||||
"Hello, Jennifer!"
|
"Hello, Jennifer!"
|
||||||
"Hello, Dave!"
|
"Hello, Dave!"
|
||||||
"Goodbye, Jennifer!"
|
"Goodbye, Jennifer!"
|
||||||
"Goodbye, Dave!"
|
"Goodbye, Dave!"
|
||||||
|
|
||||||
The keyword args given to the function are the kwargs passed into make
|
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
|
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
|
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.
|
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
|
Example with a make site arg, a call site arg, a make site kwarg and a
|
||||||
call site kwarg:
|
call site kwarg:
|
||||||
|
|
||||||
def _foo(make_arg1, call_arg1, make_location, call_location):
|
def _foo(make_arg1, call_arg1, make_location, call_location):
|
||||||
print(make_arg1 + " is from " + make_location + " and " +
|
print(make_arg1 + " is from " + make_location + " and " +
|
||||||
call_arg1 + " is from " + call_location + "!")
|
call_arg1 + " is from " + call_location + "!")
|
||||||
|
|
||||||
func = partial.make(_foo, "Ben", make_location="Hollywood")
|
func = partial.make(_foo, "Ben", make_location="Hollywood")
|
||||||
partial.call(func, "Jennifer", call_location="Denver")
|
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
|
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
|
whether they are given during the make or call step. For instance, you can't
|
||||||
do:
|
do:
|
||||||
|
|
||||||
def foo(x):
|
def foo(x):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
func = partial.make(foo, 1)
|
func = partial.make(foo, 1)
|
||||||
partial.call(func, x=2)
|
partial.call(func, x=2)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
func: The function to be called.
|
func: The function to be called.
|
||||||
*args: Positional arguments to be passed to function.
|
*args: Positional arguments to be passed to function.
|
||||||
**kwargs: Keyword arguments to be passed to function. Note that these can
|
**kwargs: Keyword arguments to be passed to function. Note that these can
|
||||||
be overridden at the call sites.
|
be overridden at the call sites.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A new `partial` that can be called using `call`
|
A new `partial` that can be called using `call`
|
||||||
"""
|
"""
|
||||||
return struct(function=func, args=args, kwargs=kwargs)
|
return struct(function = func, args = args, kwargs = kwargs)
|
||||||
|
|
||||||
partial = struct(
|
partial = struct(
|
||||||
make=_make,
|
make = _make,
|
||||||
call=_call,
|
call = _call,
|
||||||
)
|
)
|
||||||
|
|
339
lib/paths.bzl
339
lib/paths.bzl
|
@ -19,233 +19,224 @@ path separators (forward slash, "/"); they do not handle Windows-style paths
|
||||||
with backslash separators or drive letters.
|
with backslash separators or drive letters.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def _basename(p):
|
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.
|
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
|
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 Unix `basename` command (which would return the path segment preceding
|
||||||
the final slash).
|
the final slash).
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
p: The path whose basename should be returned.
|
p: The path whose basename should be returned.
|
||||||
|
|
||||||
Returns:
|
|
||||||
The basename of the path, which includes the extension.
|
|
||||||
"""
|
|
||||||
return p.rpartition("/")[-1]
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The basename of the path, which includes the extension.
|
||||||
|
"""
|
||||||
|
return p.rpartition("/")[-1]
|
||||||
|
|
||||||
def _dirname(p):
|
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
|
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
|
(i.e., the basename). Any slashes immediately preceding the basename are not
|
||||||
included, unless omitting them would make the dirname empty.
|
included, unless omitting them would make the dirname empty.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
p: The path whose dirname should be returned.
|
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("/")
|
|
||||||
|
|
||||||
|
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):
|
def _is_absolute(path):
|
||||||
"""Returns `True` if `path` is an absolute path.
|
"""Returns `True` if `path` is an absolute path.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path: A path (which is a string).
|
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] == ":")
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
`True` if `path` is an absolute path.
|
||||||
|
"""
|
||||||
|
return path.startswith("/") or (len(path) > 2 and path[1] == ":")
|
||||||
|
|
||||||
def _join(path, *others):
|
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
|
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`,
|
platform. It returns the concatenation of `path` and any members of `others`,
|
||||||
inserting directory separators before each component except the first. The
|
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
|
separator is not inserted if the path up until that point is either empty or
|
||||||
already ends in a separator.
|
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:
|
Args:
|
||||||
path: A path segment.
|
path: A path segment.
|
||||||
*others: Additional path segments.
|
*others: Additional path segments.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A string containing the joined paths.
|
A string containing the joined paths.
|
||||||
"""
|
"""
|
||||||
result = path
|
result = path
|
||||||
|
|
||||||
for p in others:
|
for p in others:
|
||||||
if _is_absolute(p):
|
if _is_absolute(p):
|
||||||
result = p
|
result = p
|
||||||
elif not result or result.endswith("/"):
|
elif not result or result.endswith("/"):
|
||||||
result += p
|
result += p
|
||||||
else:
|
else:
|
||||||
result += "/" + p
|
result += "/" + p
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
def _normalize(path):
|
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
|
This function mimics the behavior of Python's `os.path.normpath` function on
|
||||||
POSIX platforms; specifically:
|
POSIX platforms; specifically:
|
||||||
|
|
||||||
- If the entire path is empty, "." is returned.
|
- If the entire path is empty, "." is returned.
|
||||||
- All "." segments are removed, unless the path consists solely of a single
|
- All "." segments are removed, unless the path consists solely of a single
|
||||||
"." segment.
|
"." segment.
|
||||||
- Trailing slashes are removed, unless the path consists solely of slashes.
|
- Trailing slashes are removed, unless the path consists solely of slashes.
|
||||||
- ".." segments are removed as long as there are corresponding segments
|
- ".." segments are removed as long as there are corresponding segments
|
||||||
earlier in the path to remove; otherwise, they are retained as leading ".."
|
earlier in the path to remove; otherwise, they are retained as leading ".."
|
||||||
segments.
|
segments.
|
||||||
- Single and double leading slashes are preserved, but three or more leading
|
- Single and double leading slashes are preserved, but three or more leading
|
||||||
slashes are collapsed into a single leading slash.
|
slashes are collapsed into a single leading slash.
|
||||||
- Multiple adjacent internal slashes are collapsed into a single slash.
|
- Multiple adjacent internal slashes are collapsed into a single slash.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path: A path.
|
path: A path.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The normalized path.
|
The normalized path.
|
||||||
"""
|
"""
|
||||||
if not path:
|
if not path:
|
||||||
return "."
|
return "."
|
||||||
|
|
||||||
if path.startswith("//") and not path.startswith("///"):
|
if path.startswith("//") and not path.startswith("///"):
|
||||||
initial_slashes = 2
|
initial_slashes = 2
|
||||||
elif path.startswith("/"):
|
elif path.startswith("/"):
|
||||||
initial_slashes = 1
|
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)
|
|
||||||
else:
|
else:
|
||||||
new_components.append(component)
|
initial_slashes = 0
|
||||||
|
is_relative = (initial_slashes == 0)
|
||||||
|
|
||||||
path = "/".join(new_components)
|
components = path.split("/")
|
||||||
if not is_relative:
|
new_components = []
|
||||||
path = ("/" * initial_slashes) + path
|
|
||||||
|
|
||||||
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):
|
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
|
Because we do not have access to the underlying file system, this
|
||||||
implementation differs slightly from Python's `os.path.relpath` in that it
|
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
|
will fail if `path` is not beneath `start` (rather than use parent segments to
|
||||||
walk up to the common file system root).
|
walk up to the common file system root).
|
||||||
|
|
||||||
Relativizing paths that start with parent directory references only works if
|
Relativizing paths that start with parent directory references only works if
|
||||||
the path both start with the same initial parent references.
|
the path both start with the same initial parent references.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path: The path to relativize.
|
path: The path to relativize.
|
||||||
start: The ancestor path against which to relativize.
|
start: The ancestor path against which to relativize.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The portion of `path` that is relative to `start`.
|
The portion of `path` that is relative to `start`.
|
||||||
"""
|
"""
|
||||||
segments = _normalize(path).split("/")
|
segments = _normalize(path).split("/")
|
||||||
start_segments = _normalize(start).split("/")
|
start_segments = _normalize(start).split("/")
|
||||||
if start_segments == ["."]:
|
if start_segments == ["."]:
|
||||||
start_segments = []
|
start_segments = []
|
||||||
start_length = len(start_segments)
|
start_length = len(start_segments)
|
||||||
|
|
||||||
if (path.startswith("/") != start.startswith("/") or
|
if (path.startswith("/") != start.startswith("/") or
|
||||||
len(segments) < start_length):
|
len(segments) < start_length):
|
||||||
fail("Path '%s' is not beneath '%s'" % (path, start))
|
fail("Path '%s' is not beneath '%s'" % (path, start))
|
||||||
|
|
||||||
for ancestor_segment, segment in zip(start_segments, segments):
|
for ancestor_segment, segment in zip(start_segments, segments):
|
||||||
if ancestor_segment != segment:
|
if ancestor_segment != segment:
|
||||||
fail("Path '%s' is not beneath '%s'" % (path, start))
|
fail("Path '%s' is not beneath '%s'" % (path, start))
|
||||||
|
|
||||||
length = len(segments) - start_length
|
|
||||||
result_segments = segments[-length:]
|
|
||||||
return "/".join(result_segments)
|
|
||||||
|
|
||||||
|
length = len(segments) - start_length
|
||||||
|
result_segments = segments[-length:]
|
||||||
|
return "/".join(result_segments)
|
||||||
|
|
||||||
def _replace_extension(p, new_extension):
|
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:
|
Args:
|
||||||
p: The path whose extension should be replaced.
|
p: The path whose extension should be replaced.
|
||||||
new_extension: The new extension for the file. The new extension should
|
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.
|
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
|
|
||||||
|
|
||||||
|
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):
|
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
|
Leading periods on the basename are ignored, so
|
||||||
`path.split_extension(".bashrc")` returns `(".bashrc", "")`.
|
`path.split_extension(".bashrc")` returns `(".bashrc", "")`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
p: The path whose root and extension should be split.
|
p: The path whose root and extension should be split.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A tuple `(root, ext)` such that the root is the path without the file
|
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
|
extension, and `ext` is the file extension (which, if non-empty, contains
|
||||||
the leading dot). The returned tuple always satisfies the relationship
|
the leading dot). The returned tuple always satisfies the relationship
|
||||||
`root + ext == p`.
|
`root + ext == p`.
|
||||||
"""
|
"""
|
||||||
b = _basename(p)
|
b = _basename(p)
|
||||||
last_dot_in_basename = b.rfind(".")
|
last_dot_in_basename = b.rfind(".")
|
||||||
|
|
||||||
# If there is no dot or the only dot in the basename is at the front, then
|
# If there is no dot or the only dot in the basename is at the front, then
|
||||||
# there is no extension.
|
# there is no extension.
|
||||||
if last_dot_in_basename <= 0:
|
if last_dot_in_basename <= 0:
|
||||||
return (p, "")
|
return (p, "")
|
||||||
|
|
||||||
dot_distance_from_end = len(b) - last_dot_in_basename
|
|
||||||
return (p[:-dot_distance_from_end], p[-dot_distance_from_end:])
|
|
||||||
|
|
||||||
|
dot_distance_from_end = len(b) - last_dot_in_basename
|
||||||
|
return (p[:-dot_distance_from_end], p[-dot_distance_from_end:])
|
||||||
|
|
||||||
paths = struct(
|
paths = struct(
|
||||||
basename=_basename,
|
basename = _basename,
|
||||||
dirname=_dirname,
|
dirname = _dirname,
|
||||||
is_absolute=_is_absolute,
|
is_absolute = _is_absolute,
|
||||||
join=_join,
|
join = _join,
|
||||||
normalize=_normalize,
|
normalize = _normalize,
|
||||||
relativize=_relativize,
|
relativize = _relativize,
|
||||||
replace_extension=_replace_extension,
|
replace_extension = _replace_extension,
|
||||||
split_extension=_split_extension,
|
split_extension = _split_extension,
|
||||||
)
|
)
|
||||||
|
|
102
lib/selects.bzl
102
lib/selects.bzl
|
@ -14,71 +14,69 @@
|
||||||
|
|
||||||
"""Skylib module containing convenience interfaces for select()."""
|
"""Skylib module containing convenience interfaces for select()."""
|
||||||
|
|
||||||
def _with_or(input_dict, no_match_error=''):
|
def _with_or(input_dict, no_match_error = ""):
|
||||||
"""Drop-in replacement for `select()` that supports ORed keys.
|
"""Drop-in replacement for `select()` that supports ORed keys.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
input_dict: The same dictionary `select()` takes, except keys may take
|
input_dict: The same dictionary `select()` takes, except keys may take
|
||||||
either the usual form `"//foo:config1"` or
|
either the usual form `"//foo:config1"` or
|
||||||
`("//foo:config1", "//foo:config2", ...)` to signify
|
`("//foo:config1", "//foo:config2", ...)` to signify
|
||||||
`//foo:config1` OR `//foo:config2` OR `...`.
|
`//foo:config1` OR `//foo:config2` OR `...`.
|
||||||
no_match_error: Optional custom error to report if no condition matches.
|
no_match_error: Optional custom error to report if no condition matches.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```build
|
```build
|
||||||
deps = selects.with_or({
|
deps = selects.with_or({
|
||||||
"//configs:one": [":dep1"],
|
"//configs:one": [":dep1"],
|
||||||
("//configs:two", "//configs:three"): [":dep2or3"],
|
("//configs:two", "//configs:three"): [":dep2or3"],
|
||||||
"//configs:four": [":dep4"],
|
"//configs:four": [":dep4"],
|
||||||
"//conditions:default": [":default"]
|
"//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:
|
Returns:
|
||||||
A native `select()` that expands
|
A native `select()` that expands
|
||||||
|
|
||||||
`("//configs:two", "//configs:three"): [":dep2or3"]`
|
`("//configs:two", "//configs:three"): [":dep2or3"]`
|
||||||
|
|
||||||
to
|
to
|
||||||
|
|
||||||
```build
|
|
||||||
"//configs:two": [":dep2or3"],
|
|
||||||
"//configs:three": [":dep2or3"],
|
|
||||||
```
|
|
||||||
"""
|
|
||||||
return select(_with_or_dict(input_dict), no_match_error=no_match_error)
|
|
||||||
|
|
||||||
|
```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):
|
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
|
Unlike `select()`, the contents of the dict can be inspected by Skylark
|
||||||
macros.
|
macros.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
input_dict: Same as `with_or`.
|
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
|
|
||||||
|
|
||||||
|
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(
|
selects = struct(
|
||||||
with_or=_with_or,
|
with_or = _with_or,
|
||||||
with_or_dict=_with_or_dict
|
with_or_dict = _with_or_dict,
|
||||||
)
|
)
|
||||||
|
|
150
lib/sets.bzl
150
lib/sets.bzl
|
@ -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.
|
them as the `set` type, regardless of the types of the inputs.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def _precondition_only_sets_or_lists(*args):
|
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.
|
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))
|
|
||||||
|
|
||||||
|
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):
|
def _is_equal(a, b):
|
||||||
"""Returns whether two sets are equal.
|
"""Returns whether two sets are equal.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
a: A depset or a list.
|
a: A depset or a list.
|
||||||
b: 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))
|
|
||||||
|
|
||||||
|
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):
|
def _is_subset(a, b):
|
||||||
"""Returns whether `a` is a subset of `b`.
|
"""Returns whether `a` is a subset of `b`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
a: A depset or a list.
|
a: A depset or a list.
|
||||||
b: 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
|
|
||||||
|
|
||||||
|
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):
|
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:
|
Args:
|
||||||
a: A set or list.
|
a: A set or list.
|
||||||
b: 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
|
|
||||||
|
|
||||||
|
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):
|
def _intersection(a, b):
|
||||||
"""Returns the intersection of two sets.
|
"""Returns the intersection of two sets.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
a: A set or list.
|
a: A set or list.
|
||||||
b: 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])
|
|
||||||
|
|
||||||
|
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):
|
def _union(*args):
|
||||||
"""Returns the union of several sets.
|
"""Returns the union of several sets.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
*args: An arbitrary number of sets or lists.
|
*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)
|
|
||||||
|
|
||||||
|
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):
|
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:
|
Args:
|
||||||
a: A set or list.
|
a: A set or list.
|
||||||
b: 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])
|
|
||||||
|
|
||||||
|
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(
|
sets = struct(
|
||||||
difference = _difference,
|
difference = _difference,
|
||||||
|
|
|
@ -14,44 +14,41 @@
|
||||||
|
|
||||||
"""Skylib module containing shell utility functions."""
|
"""Skylib module containing shell utility functions."""
|
||||||
|
|
||||||
|
|
||||||
def _array_literal(iterable):
|
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
|
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
|
`("a" "b" "c")`, which can be used in a shell script wherever an array
|
||||||
literal is needed.
|
literal is needed.
|
||||||
|
|
||||||
Note that all elements in the array are quoted (using `shell.quote`) for
|
Note that all elements in the array are quoted (using `shell.quote`) for
|
||||||
safety, even if they do not need to be.
|
safety, even if they do not need to be.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
iterable: A sequence of elements. Elements that are not strings will be
|
iterable: A sequence of elements. Elements that are not strings will be
|
||||||
converted to strings first, by calling `str()`.
|
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]) + ")"
|
|
||||||
|
|
||||||
|
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):
|
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
|
This function quotes the given string (in case it contains spaces or other
|
||||||
shell metacharacters.)
|
shell metacharacters.)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
s: The string to quote.
|
s: The string to quote.
|
||||||
|
|
||||||
Returns:
|
|
||||||
A quoted version of the string that can be passed to a shell command.
|
|
||||||
"""
|
|
||||||
return "'" + s.replace("'", "'\\''") + "'"
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A quoted version of the string that can be passed to a shell command.
|
||||||
|
"""
|
||||||
|
return "'" + s.replace("'", "'\\''") + "'"
|
||||||
|
|
||||||
shell = struct(
|
shell = struct(
|
||||||
array_literal=_array_literal,
|
array_literal = _array_literal,
|
||||||
quote=_quote,
|
quote = _quote,
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,24 +14,22 @@
|
||||||
|
|
||||||
"""Skylib module containing functions that operate on structs."""
|
"""Skylib module containing functions that operate on structs."""
|
||||||
|
|
||||||
|
|
||||||
def _to_dict(s):
|
def _to_dict(s):
|
||||||
"""Converts a `struct` to a `dict`.
|
"""Converts a `struct` to a `dict`.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
s: A `struct`.
|
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}
|
|
||||||
|
|
||||||
|
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(
|
structs = struct(
|
||||||
to_dict=_to_dict,
|
to_dict = _to_dict,
|
||||||
)
|
)
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
"""Skylib module containing functions checking types."""
|
"""Skylib module containing functions checking types."""
|
||||||
|
|
||||||
|
|
||||||
# create instance singletons to avoid unnecessary allocations
|
# create instance singletons to avoid unnecessary allocations
|
||||||
_a_bool = True
|
_a_bool = True
|
||||||
_a_dict = {}
|
_a_dict = {}
|
||||||
|
@ -22,10 +21,8 @@ _a_string = ""
|
||||||
_a_tuple = ()
|
_a_tuple = ()
|
||||||
_an_int = 1
|
_an_int = 1
|
||||||
|
|
||||||
|
|
||||||
def _a_function():
|
def _a_function():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def _is_list(v):
|
def _is_list(v):
|
||||||
"""Returns True if v is an instance of a list.
|
"""Returns True if v is an instance of a list.
|
||||||
|
@ -38,7 +35,6 @@ def _is_list(v):
|
||||||
"""
|
"""
|
||||||
return type(v) == type(_a_list)
|
return type(v) == type(_a_list)
|
||||||
|
|
||||||
|
|
||||||
def _is_string(v):
|
def _is_string(v):
|
||||||
"""Returns True if v is an instance of a string.
|
"""Returns True if v is an instance of a string.
|
||||||
|
|
||||||
|
@ -50,7 +46,6 @@ def _is_string(v):
|
||||||
"""
|
"""
|
||||||
return type(v) == type(_a_string)
|
return type(v) == type(_a_string)
|
||||||
|
|
||||||
|
|
||||||
def _is_bool(v):
|
def _is_bool(v):
|
||||||
"""Returns True if v is an instance of a bool.
|
"""Returns True if v is an instance of a bool.
|
||||||
|
|
||||||
|
@ -62,7 +57,6 @@ def _is_bool(v):
|
||||||
"""
|
"""
|
||||||
return type(v) == type(_a_bool)
|
return type(v) == type(_a_bool)
|
||||||
|
|
||||||
|
|
||||||
def _is_none(v):
|
def _is_none(v):
|
||||||
"""Returns True if v has the type of None.
|
"""Returns True if v has the type of None.
|
||||||
|
|
||||||
|
@ -74,7 +68,6 @@ def _is_none(v):
|
||||||
"""
|
"""
|
||||||
return type(v) == type(None)
|
return type(v) == type(None)
|
||||||
|
|
||||||
|
|
||||||
def _is_int(v):
|
def _is_int(v):
|
||||||
"""Returns True if v is an instance of a signed integer.
|
"""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)
|
return type(v) == type(_an_int)
|
||||||
|
|
||||||
|
|
||||||
def _is_tuple(v):
|
def _is_tuple(v):
|
||||||
"""Returns True if v is an instance of a tuple.
|
"""Returns True if v is an instance of a tuple.
|
||||||
|
|
||||||
|
@ -98,7 +90,6 @@ def _is_tuple(v):
|
||||||
"""
|
"""
|
||||||
return type(v) == type(_a_tuple)
|
return type(v) == type(_a_tuple)
|
||||||
|
|
||||||
|
|
||||||
def _is_dict(v):
|
def _is_dict(v):
|
||||||
"""Returns True if v is an instance of a dict.
|
"""Returns True if v is an instance of a dict.
|
||||||
|
|
||||||
|
@ -110,7 +101,6 @@ def _is_dict(v):
|
||||||
"""
|
"""
|
||||||
return type(v) == type(_a_dict)
|
return type(v) == type(_a_dict)
|
||||||
|
|
||||||
|
|
||||||
def _is_function(v):
|
def _is_function(v):
|
||||||
"""Returns True if v is an instance of a function.
|
"""Returns True if v is an instance of a function.
|
||||||
|
|
||||||
|
@ -122,14 +112,13 @@ def _is_function(v):
|
||||||
"""
|
"""
|
||||||
return type(v) == type(_a_function)
|
return type(v) == type(_a_function)
|
||||||
|
|
||||||
|
|
||||||
types = struct(
|
types = struct(
|
||||||
is_list=_is_list,
|
is_list = _is_list,
|
||||||
is_string=_is_string,
|
is_string = _is_string,
|
||||||
is_bool=_is_bool,
|
is_bool = _is_bool,
|
||||||
is_none=_is_none,
|
is_none = _is_none,
|
||||||
is_int=_is_int,
|
is_int = _is_int,
|
||||||
is_tuple=_is_tuple,
|
is_tuple = _is_tuple,
|
||||||
is_dict=_is_dict,
|
is_dict = _is_dict,
|
||||||
is_function=_is_function,
|
is_function = _is_function,
|
||||||
)
|
)
|
||||||
|
|
433
lib/unittest.bzl
433
lib/unittest.bzl
|
@ -20,272 +20,265 @@ assertions used to within tests.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
load(":sets.bzl", "sets")
|
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):
|
Each unit test is defined in an implementation function that must then be
|
||||||
"""Creates a unit test rule from its implementation function.
|
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
|
The optional `attrs` argument can be used to define dependencies for this
|
||||||
associated with a rule so that a target can be built. This function handles
|
test, in order to form unit tests of rules.
|
||||||
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
|
An example of a unit test:
|
||||||
test, in order to form unit tests of rules.
|
|
||||||
|
|
||||||
An example of a unit test:
|
```
|
||||||
|
def _your_test(ctx):
|
||||||
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
```
|
# Assert statements go here
|
||||||
def _your_test(ctx):
|
|
||||||
env = unittest.begin(ctx)
|
|
||||||
|
|
||||||
# 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:
|
Returns:
|
||||||
impl: The implementation function of the unit test.
|
A rule definition that should be stored in a global whose name ends in
|
||||||
attrs: An optional dictionary to supplement the attrs passed to the
|
`_test`.
|
||||||
unit test's `rule()` constructor.
|
"""
|
||||||
|
|
||||||
Returns:
|
# Derive the name of the implementation function for better test feedback.
|
||||||
A rule definition that should be stored in a global whose name ends in
|
# Skylark currently stringifies a function as "<function NAME>", so we use
|
||||||
`_test`.
|
# 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.
|
attrs = dict(attrs) if attrs else {}
|
||||||
# Skylark currently stringifies a function as "<function NAME>", so we use
|
attrs["_impl_name"] = attr.string(default = impl_name)
|
||||||
# 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,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
return rule(
|
||||||
|
impl,
|
||||||
|
attrs = attrs,
|
||||||
|
_skylark_testable = True,
|
||||||
|
test = True,
|
||||||
|
)
|
||||||
|
|
||||||
def _suite(name, *test_rules):
|
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
|
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
|
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
|
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
|
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
|
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.
|
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 --
|
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
|
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
|
create the targets and wrap them in a single test_suite target. In your
|
||||||
`.bzl` file, write:
|
`.bzl` file, write:
|
||||||
|
|
||||||
```
|
```
|
||||||
def your_test_suite():
|
def your_test_suite():
|
||||||
unittest.suite(
|
unittest.suite(
|
||||||
"your_test_suite",
|
"your_test_suite",
|
||||||
your_test,
|
your_test,
|
||||||
your_other_test,
|
your_other_test,
|
||||||
yet_another_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):
|
def _begin(ctx):
|
||||||
"""Begins a unit test.
|
"""Begins a unit test.
|
||||||
|
|
||||||
This should be the first function called in a unit test implementation
|
This should be the first function called in a unit test implementation
|
||||||
function. It initializes a "test environment" that is used to collect
|
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
|
assertion failures so that they can be reported and logged at the end of the
|
||||||
test.
|
test.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
ctx: The Skylark context. Pass the implementation function's `ctx` argument
|
ctx: The Skylark context. Pass the implementation function's `ctx` argument
|
||||||
in verbatim.
|
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=[])
|
|
||||||
|
|
||||||
|
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):
|
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
|
This must be called before the end of a unit test implementation function so
|
||||||
that the results are reported.
|
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,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
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):
|
def _fail(env, msg):
|
||||||
"""Unconditionally causes the current test to fail.
|
"""Unconditionally causes the current test to fail.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
env: The test environment returned by `unittest.begin`.
|
env: The test environment returned by `unittest.begin`.
|
||||||
msg: The message to log describing the failure.
|
msg: The message to log describing the failure.
|
||||||
"""
|
"""
|
||||||
full_msg = "In test %s: %s" % (env.ctx.attr._impl_name, msg)
|
full_msg = "In test %s: %s" % (env.ctx.attr._impl_name, msg)
|
||||||
print(full_msg)
|
print(full_msg)
|
||||||
env.failures.append(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,
|
Args:
|
||||||
condition,
|
env: The test environment returned by `unittest.begin`.
|
||||||
msg="Expected condition to be true, but was false."):
|
condition: A value that will be evaluated in a Boolean context.
|
||||||
"""Asserts that the given `condition` is true.
|
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:
|
def _assert_false(
|
||||||
env: The test environment returned by `unittest.begin`.
|
env,
|
||||||
condition: A value that will be evaluated in a Boolean context.
|
condition,
|
||||||
msg: An optional message that will be printed that describes the failure.
|
msg = "Expected condition to be false, but was true."):
|
||||||
If omitted, a default will be used.
|
"""Asserts that the given `condition` is false.
|
||||||
"""
|
|
||||||
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 condition:
|
||||||
|
_fail(env, msg)
|
||||||
|
|
||||||
def _assert_false(env,
|
def _assert_equals(env, expected, actual, msg = None):
|
||||||
condition,
|
"""Asserts that the given `expected` and `actual` values are equal.
|
||||||
msg="Expected condition to be false, but was true."):
|
|
||||||
"""Asserts that the given `condition` is false.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
env: The test environment returned by `unittest.begin`.
|
env: The test environment returned by `unittest.begin`.
|
||||||
condition: A value that will be evaluated in a Boolean context.
|
expected: The expected value of some computation.
|
||||||
msg: An optional message that will be printed that describes the failure.
|
actual: The actual value returned by some computation.
|
||||||
If omitted, a default will be used.
|
msg: An optional message that will be printed that describes the failure.
|
||||||
"""
|
If omitted, a default will be used.
|
||||||
if condition:
|
"""
|
||||||
_fail(env, msg)
|
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):
|
Args:
|
||||||
"""Asserts that the given `expected` and `actual` values are equal.
|
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:
|
def _assert_new_set_equals(env, expected, actual, msg = None):
|
||||||
env: The test environment returned by `unittest.begin`.
|
"""Asserts that the given `expected` and `actual` sets are equal.
|
||||||
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)
|
|
||||||
|
|
||||||
|
Args:
|
||||||
def _assert_set_equals(env, expected, actual, msg=None):
|
env: The test environment returned by `unittest.begin`.
|
||||||
"""Asserts that the given `expected` and `actual` sets are equal.
|
expected: The expected set resulting from some computation.
|
||||||
|
actual: The actual set returned by some computation.
|
||||||
Args:
|
msg: An optional message that will be printed that describes the failure.
|
||||||
env: The test environment returned by `unittest.begin`.
|
If omitted, a default will be used.
|
||||||
expected: The expected set resulting from some computation.
|
"""
|
||||||
actual: The actual set returned by some computation.
|
if not new_sets.is_equal(expected, actual):
|
||||||
msg: An optional message that will be printed that describes the failure.
|
expectation_msg = "Expected %r, but got %r" % (expected, actual)
|
||||||
If omitted, a default will be used.
|
if msg:
|
||||||
"""
|
full_msg = "%s (%s)" % (msg, expectation_msg)
|
||||||
if type(actual) != type(depset()) or not sets.is_equal(expected, actual):
|
else:
|
||||||
expectation_msg = "Expected %r, but got %r" % (expected, actual)
|
full_msg = expectation_msg
|
||||||
if msg:
|
_fail(env, full_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)
|
|
||||||
|
|
||||||
asserts = struct(
|
asserts = struct(
|
||||||
equals=_assert_equals,
|
equals = _assert_equals,
|
||||||
false=_assert_false,
|
false = _assert_false,
|
||||||
set_equals=_assert_set_equals,
|
set_equals = _assert_set_equals,
|
||||||
new_set_equals = _assert_new_set_equals,
|
new_set_equals = _assert_new_set_equals,
|
||||||
true=_assert_true,
|
true = _assert_true,
|
||||||
)
|
)
|
||||||
|
|
||||||
unittest = struct(
|
unittest = struct(
|
||||||
make=_make,
|
make = _make,
|
||||||
suite=_suite,
|
suite = _suite,
|
||||||
begin=_begin,
|
begin = _begin,
|
||||||
end=_end,
|
end = _end,
|
||||||
fail=_fail,
|
fail = _fail,
|
||||||
)
|
)
|
||||||
|
|
154
lib/versions.bzl
154
lib/versions.bzl
|
@ -15,111 +15,113 @@
|
||||||
"""Skylib module containing functions for checking Bazel versions."""
|
"""Skylib module containing functions for checking Bazel versions."""
|
||||||
|
|
||||||
def _get_bazel_version():
|
def _get_bazel_version():
|
||||||
"""Returns the current Bazel version"""
|
"""Returns the current Bazel version"""
|
||||||
|
|
||||||
return native.bazel_version
|
|
||||||
|
|
||||||
|
return native.bazel_version
|
||||||
|
|
||||||
def _extract_version_number(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:
|
Args:
|
||||||
bazel_version: the version string that begins with the semantic version
|
bazel_version: the version string that begins with the semantic version
|
||||||
e.g. "1.2.3rc1 abc1234" where "abc1234" is a commit hash.
|
e.g. "1.2.3rc1 abc1234" where "abc1234" is a commit hash.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The semantic version string, like "1.2.3".
|
The semantic version string, like "1.2.3".
|
||||||
"""
|
"""
|
||||||
for i in range(len(bazel_version)):
|
for i in range(len(bazel_version)):
|
||||||
c = bazel_version[i]
|
c = bazel_version[i]
|
||||||
if not (c.isdigit() or c == "."):
|
if not (c.isdigit() or c == "."):
|
||||||
return bazel_version[:i]
|
return bazel_version[:i]
|
||||||
return bazel_version
|
return bazel_version
|
||||||
|
|
||||||
# Parse the bazel version string from `native.bazel_version`.
|
# Parse the bazel version string from `native.bazel_version`.
|
||||||
# e.g.
|
# e.g.
|
||||||
# "0.10.0rc1 abc123d" => (0, 10, 0)
|
# "0.10.0rc1 abc123d" => (0, 10, 0)
|
||||||
# "0.3.0" => (0, 3, 0)
|
# "0.3.0" => (0, 3, 0)
|
||||||
def _parse_bazel_version(bazel_version):
|
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:
|
Args:
|
||||||
bazel_version: the Bazel version string
|
bazel_version: the Bazel version string
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
An int 3-tuple of a (major, minor, patch) version.
|
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(".")])
|
|
||||||
|
|
||||||
|
version = _extract_version_number(bazel_version)
|
||||||
|
return tuple([int(n) for n in version.split(".")])
|
||||||
|
|
||||||
def _is_at_most(threshold, version):
|
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:
|
Args:
|
||||||
threshold: the maximum version string
|
threshold: the maximum version string
|
||||||
version: the version string to be compared to the threshold
|
version: the version string to be compared to the threshold
|
||||||
|
|
||||||
Returns:
|
|
||||||
True if version <= threshold.
|
|
||||||
"""
|
|
||||||
return _parse_bazel_version(version) <= _parse_bazel_version(threshold)
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if version <= threshold.
|
||||||
|
"""
|
||||||
|
return _parse_bazel_version(version) <= _parse_bazel_version(threshold)
|
||||||
|
|
||||||
def _is_at_least(threshold, version):
|
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:
|
Args:
|
||||||
threshold: the minimum version string
|
threshold: the minimum version string
|
||||||
version: the version string to be compared to the threshold
|
version: the version string to be compared to the threshold
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if version >= threshold.
|
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):
|
Args:
|
||||||
"""Check that the version of Bazel is valid within the specified range.
|
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:
|
if not _is_at_least(
|
||||||
minimum_bazel_version: minimum version of Bazel expected
|
threshold = minimum_bazel_version,
|
||||||
maximum_bazel_version: maximum version of Bazel expected
|
version = bazel_version,
|
||||||
bazel_version: the version of Bazel to check. Used for testing, defaults to native.bazel_version
|
):
|
||||||
"""
|
fail("\nCurrent Bazel version is {}, expected at least {}\n".format(
|
||||||
if not bazel_version:
|
bazel_version,
|
||||||
if "bazel_version" not in dir(native):
|
minimum_bazel_version,
|
||||||
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(
|
if maximum_bazel_version:
|
||||||
threshold = minimum_bazel_version,
|
if not _is_at_most(
|
||||||
version = bazel_version):
|
threshold = maximum_bazel_version,
|
||||||
fail("\nCurrent Bazel version is {}, expected at least {}\n".format(
|
version = bazel_version,
|
||||||
bazel_version, minimum_bazel_version))
|
):
|
||||||
|
fail("\nCurrent Bazel version is {}, expected at most {}\n".format(
|
||||||
|
bazel_version,
|
||||||
|
maximum_bazel_version,
|
||||||
|
))
|
||||||
|
|
||||||
if maximum_bazel_version:
|
pass
|
||||||
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
|
|
||||||
|
|
||||||
versions = struct(
|
versions = struct(
|
||||||
get=_get_bazel_version,
|
get = _get_bazel_version,
|
||||||
parse=_parse_bazel_version,
|
parse = _parse_bazel_version,
|
||||||
check=_check_bazel_version,
|
check = _check_bazel_version,
|
||||||
is_at_most=_is_at_most,
|
is_at_most = _is_at_most,
|
||||||
is_at_least=_is_at_least,
|
is_at_least = _is_at_least,
|
||||||
)
|
)
|
||||||
|
|
|
@ -15,46 +15,46 @@
|
||||||
"""Skylib module containing a library rule for aggregating rules files."""
|
"""Skylib module containing a library rule for aggregating rules files."""
|
||||||
|
|
||||||
SkylarkLibraryInfo = provider(
|
SkylarkLibraryInfo = provider(
|
||||||
'Information on contained Skylark rules.',
|
"Information on contained Skylark rules.",
|
||||||
fields={
|
fields = {
|
||||||
'srcs': 'Top level rules files.',
|
"srcs": "Top level rules files.",
|
||||||
'transitive_srcs': 'Transitive closure of rules files required for ' +
|
"transitive_srcs": "Transitive closure of rules files required for " +
|
||||||
'interpretation of the srcs',
|
"interpretation of the srcs",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
def _skylark_library_impl(ctx):
|
def _skylark_library_impl(ctx):
|
||||||
deps_files = [depset(x.files, order="postorder") for x in ctx.attr.deps]
|
deps_files = [depset(x.files, order = "postorder") for x in ctx.attr.deps]
|
||||||
all_files = depset(ctx.files.srcs, order="postorder", transitive=deps_files)
|
all_files = depset(ctx.files.srcs, order = "postorder", transitive = deps_files)
|
||||||
return [
|
return [
|
||||||
# All dependent files should be listed in both `files` and in `runfiles`;
|
# All dependent files should be listed in both `files` and in `runfiles`;
|
||||||
# this ensures that a `skylark_library` can be referenced as `data` from
|
# this ensures that a `skylark_library` can be referenced as `data` from
|
||||||
# a separate program, or from `tools` of a genrule().
|
# a separate program, or from `tools` of a genrule().
|
||||||
DefaultInfo(
|
DefaultInfo(
|
||||||
files=all_files,
|
files = all_files,
|
||||||
runfiles=ctx.runfiles(files=list(all_files)),
|
runfiles = ctx.runfiles(files = list(all_files)),
|
||||||
),
|
),
|
||||||
|
|
||||||
# We also define our own provider struct, for aggregation and testing.
|
# We also define our own provider struct, for aggregation and testing.
|
||||||
SkylarkLibraryInfo(
|
SkylarkLibraryInfo(
|
||||||
srcs=ctx.files.srcs,
|
srcs = ctx.files.srcs,
|
||||||
transitive_srcs=all_files,
|
transitive_srcs = all_files,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
skylark_library = rule(
|
skylark_library = rule(
|
||||||
implementation=_skylark_library_impl,
|
implementation = _skylark_library_impl,
|
||||||
attrs={
|
attrs = {
|
||||||
"srcs": attr.label_list(
|
"srcs": attr.label_list(
|
||||||
allow_files=[".bzl"],
|
allow_files = [".bzl"],
|
||||||
),
|
),
|
||||||
"deps": attr.label_list(
|
"deps": attr.label_list(
|
||||||
allow_files=[".bzl"],
|
allow_files = [".bzl"],
|
||||||
providers=[
|
providers = [
|
||||||
[SkylarkLibraryInfo],
|
[SkylarkLibraryInfo],
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
"""Creates a logical collection of Skylark .bzl files.
|
"""Creates a logical collection of Skylark .bzl files.
|
||||||
|
|
||||||
|
|
|
@ -14,68 +14,99 @@
|
||||||
|
|
||||||
"""Unit tests for collections.bzl."""
|
"""Unit tests for collections.bzl."""
|
||||||
|
|
||||||
load("//:lib.bzl", "collections", "asserts", "unittest")
|
load("//:lib.bzl", "asserts", "collections", "unittest")
|
||||||
|
|
||||||
|
|
||||||
def _after_each_test(ctx):
|
def _after_each_test(ctx):
|
||||||
"""Unit tests for collections.after_each."""
|
"""Unit tests for collections.after_each."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.equals(env, [], collections.after_each("1", []))
|
asserts.equals(env, [], collections.after_each("1", []))
|
||||||
asserts.equals(env, ["a", "1"], collections.after_each("1", ["a"]))
|
asserts.equals(env, ["a", "1"], collections.after_each("1", ["a"]))
|
||||||
asserts.equals(env, ["a", "1", "b", "1"],
|
asserts.equals(
|
||||||
collections.after_each("1", ["a", "b"]))
|
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
|
# We don't care what type the separator is, we just put it there; so None
|
||||||
# should be just as valid as anything else.
|
# should be just as valid as anything else.
|
||||||
asserts.equals(env, ["a", None, "b", None],
|
asserts.equals(
|
||||||
collections.after_each(None, ["a", "b"]))
|
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)
|
after_each_test = unittest.make(_after_each_test)
|
||||||
|
|
||||||
|
|
||||||
def _before_each_test(ctx):
|
def _before_each_test(ctx):
|
||||||
"""Unit tests for collections.before_each."""
|
"""Unit tests for collections.before_each."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.equals(env, [], collections.before_each("1", []))
|
asserts.equals(env, [], collections.before_each("1", []))
|
||||||
asserts.equals(env, ["1", "a"], collections.before_each("1", ["a"]))
|
asserts.equals(env, ["1", "a"], collections.before_each("1", ["a"]))
|
||||||
asserts.equals(env, ["1", "a", "1", "b"],
|
asserts.equals(
|
||||||
collections.before_each("1", ["a", "b"]))
|
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
|
# We don't care what type the separator is, we just put it there; so None
|
||||||
# should be just as valid as anything else.
|
# should be just as valid as anything else.
|
||||||
asserts.equals(env, [None, "a", None, "b"],
|
asserts.equals(
|
||||||
collections.before_each(None, ["a", "b"]))
|
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)
|
before_each_test = unittest.make(_before_each_test)
|
||||||
|
|
||||||
|
|
||||||
def _uniq_test(ctx):
|
def _uniq_test(ctx):
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
asserts.equals(env, collections.uniq([0, 1, 2, 3]), [0, 1, 2, 3])
|
asserts.equals(env, collections.uniq([0, 1, 2, 3]), [0, 1, 2, 3])
|
||||||
asserts.equals(env, collections.uniq([]), [])
|
asserts.equals(env, collections.uniq([]), [])
|
||||||
asserts.equals(env, collections.uniq([1, 1, 1, 1, 1]), [1])
|
asserts.equals(env, collections.uniq([1, 1, 1, 1, 1]), [1])
|
||||||
asserts.equals(env, collections.uniq([True, 5, "foo", 5, False, struct(a=1),
|
asserts.equals(
|
||||||
True, struct(b=2), "bar", (1,), "foo",
|
env,
|
||||||
struct(a=1), (1,)]),
|
collections.uniq([
|
||||||
[True, 5, "foo", False, struct(a=1), struct(b=2),
|
True,
|
||||||
"bar", (1,)])
|
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)
|
uniq_test = unittest.make(_uniq_test)
|
||||||
|
|
||||||
|
|
||||||
def collections_test_suite():
|
def collections_test_suite():
|
||||||
"""Creates the test targets and test suite for collections.bzl tests."""
|
"""Creates the test targets and test suite for collections.bzl tests."""
|
||||||
unittest.suite(
|
unittest.suite(
|
||||||
"collections_tests",
|
"collections_tests",
|
||||||
after_each_test,
|
after_each_test,
|
||||||
before_each_test,
|
before_each_test,
|
||||||
uniq_test,
|
uniq_test,
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,54 +14,61 @@
|
||||||
|
|
||||||
"""Unit tests for dicts.bzl."""
|
"""Unit tests for dicts.bzl."""
|
||||||
|
|
||||||
load("//:lib.bzl", "dicts", "asserts", "unittest")
|
load("//:lib.bzl", "asserts", "dicts", "unittest")
|
||||||
|
|
||||||
|
|
||||||
def _add_test(ctx):
|
def _add_test(ctx):
|
||||||
"""Unit tests for dicts.add."""
|
"""Unit tests for dicts.add."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
# Test zero- and one-argument behavior.
|
# Test zero- and one-argument behavior.
|
||||||
asserts.equals(env, {}, dicts.add())
|
asserts.equals(env, {}, dicts.add())
|
||||||
asserts.equals(env, {"a": 1}, dicts.add({"a": 1}))
|
asserts.equals(env, {"a": 1}, dicts.add({"a": 1}))
|
||||||
|
|
||||||
# Test simple two-argument behavior.
|
# Test simple two-argument behavior.
|
||||||
asserts.equals(env, {"a": 1, "b": 2}, dicts.add({"a": 1}, {"b": 2}))
|
asserts.equals(env, {"a": 1, "b": 2}, dicts.add({"a": 1}, {"b": 2}))
|
||||||
|
|
||||||
# Test simple more-than-two-argument behavior.
|
# Test simple more-than-two-argument behavior.
|
||||||
asserts.equals(env, {"a": 1, "b": 2, "c": 3, "d": 4},
|
asserts.equals(
|
||||||
dicts.add({"a": 1}, {"b": 2}, {"c": 3}, {"d": 4}))
|
env,
|
||||||
|
{"a": 1, "b": 2, "c": 3, "d": 4},
|
||||||
|
dicts.add({"a": 1}, {"b": 2}, {"c": 3}, {"d": 4}),
|
||||||
|
)
|
||||||
|
|
||||||
# Test same-key overriding.
|
# Test same-key overriding.
|
||||||
asserts.equals(env, {"a": 100}, dicts.add({"a": 1}, {"a": 100}))
|
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": 10}, dicts.add({"a": 1}, {"a": 100}, {"a": 10}))
|
||||||
asserts.equals(env, {"a": 100, "b": 10},
|
asserts.equals(
|
||||||
dicts.add({"a": 1}, {"a": 100}, {"b": 10}))
|
env,
|
||||||
asserts.equals(env, {"a": 10}, dicts.add({"a": 1}, {}, {"a": 10}))
|
{"a": 100, "b": 10},
|
||||||
asserts.equals(env, {"a": 10, "b": 5},
|
dicts.add({"a": 1}, {"a": 100}, {"b": 10}),
|
||||||
dicts.add({"a": 1}, {"a": 10, "b": 5}))
|
)
|
||||||
|
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.
|
# Test some other boundary cases.
|
||||||
asserts.equals(env, {"a": 1}, dicts.add({"a": 1}, {}))
|
asserts.equals(env, {"a": 1}, dicts.add({"a": 1}, {}))
|
||||||
|
|
||||||
# Since dictionaries are passed around by reference, make sure that the
|
# Since dictionaries are passed around by reference, make sure that the
|
||||||
# result of dicts.add is always a *copy* by modifying it afterwards and
|
# 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
|
# 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
|
# this to protect against someone who might attempt to optimize the function
|
||||||
# by returning the argument itself in the one-argument case.
|
# by returning the argument itself in the one-argument case.
|
||||||
original = {"a": 1}
|
original = {"a": 1}
|
||||||
result = dicts.add(original)
|
result = dicts.add(original)
|
||||||
result["a"] = 2
|
result["a"] = 2
|
||||||
asserts.equals(env, 1, original["a"])
|
asserts.equals(env, 1, original["a"])
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
add_test = unittest.make(_add_test)
|
add_test = unittest.make(_add_test)
|
||||||
|
|
||||||
|
|
||||||
def dicts_test_suite():
|
def dicts_test_suite():
|
||||||
"""Creates the test targets and test suite for dicts.bzl tests."""
|
"""Creates the test targets and test suite for dicts.bzl tests."""
|
||||||
unittest.suite(
|
unittest.suite(
|
||||||
"dicts_tests",
|
"dicts_tests",
|
||||||
add_test,
|
add_test,
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,272 +14,264 @@
|
||||||
|
|
||||||
"""Unit tests for new_sets.bzl."""
|
"""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):
|
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
|
# 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
|
# be inconclusive because they use `asserts.new_set_equals`, which in turn
|
||||||
# calls `new_sets.is_equal`.
|
# calls `new_sets.is_equal`.
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.true(env, new_sets.is_equal(new_sets.make(), new_sets.make()))
|
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(), new_sets.make([1])))
|
||||||
asserts.false(env, new_sets.is_equal(new_sets.make([1]), new_sets.make()))
|
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.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([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([2])))
|
||||||
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([1, 2])))
|
||||||
|
|
||||||
# Verify that the implementation is not using == on the sets directly.
|
# 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]))))
|
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.
|
# 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])))
|
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)
|
is_equal_test = unittest.make(_is_equal_test)
|
||||||
|
|
||||||
|
|
||||||
def _is_subset_test(ctx):
|
def _is_subset_test(ctx):
|
||||||
"""Unit tests for new_sets.is_subset."""
|
"""Unit tests for new_sets.is_subset."""
|
||||||
env = unittest.begin(ctx)
|
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()))
|
||||||
asserts.true(env, new_sets.is_subset(new_sets.make(), new_sets.make([1])))
|
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.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])))
|
||||||
asserts.true(env, new_sets.is_subset(new_sets.make([1]), new_sets.make([1, 2])))
|
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.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([1]), new_sets.make(depset([1, 2]))))
|
||||||
|
|
||||||
# If passing a list, verify that duplicate elements are ignored.
|
# 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])))
|
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)
|
is_subset_test = unittest.make(_is_subset_test)
|
||||||
|
|
||||||
|
|
||||||
def _disjoint_test(ctx):
|
def _disjoint_test(ctx):
|
||||||
"""Unit tests for new_sets.disjoint."""
|
"""Unit tests for new_sets.disjoint."""
|
||||||
env = unittest.begin(ctx)
|
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()))
|
||||||
asserts.true(env, new_sets.disjoint(new_sets.make(), new_sets.make([1])))
|
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.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])))
|
||||||
asserts.false(env, new_sets.disjoint(new_sets.make([1]), new_sets.make([1, 2])))
|
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([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([1]), new_sets.make(depset([2]))))
|
||||||
|
|
||||||
# If passing a list, verify that duplicate elements are ignored.
|
# 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])))
|
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)
|
disjoint_test = unittest.make(_disjoint_test)
|
||||||
|
|
||||||
|
|
||||||
def _intersection_test(ctx):
|
def _intersection_test(ctx):
|
||||||
"""Unit tests for new_sets.intersection."""
|
"""Unit tests for new_sets.intersection."""
|
||||||
env = unittest.begin(ctx)
|
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()))
|
||||||
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(), 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(), 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])))
|
||||||
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([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(), 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([1]), new_sets.intersection(new_sets.make([1]), new_sets.make(depset([1]))))
|
||||||
|
|
||||||
# If passing a list, verify that duplicate elements are ignored.
|
# 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])))
|
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)
|
intersection_test = unittest.make(_intersection_test)
|
||||||
|
|
||||||
|
|
||||||
def _union_test(ctx):
|
def _union_test(ctx):
|
||||||
"""Unit tests for new_sets.union."""
|
"""Unit tests for new_sets.union."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.new_set_equals(env, new_sets.make(), new_sets.union())
|
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([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(), 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(), 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()))
|
||||||
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]), 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([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, 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([1]), new_sets.union(new_sets.make([1]), new_sets.make(depset([1]))))
|
||||||
|
|
||||||
# If passing a list, verify that duplicate elements are ignored.
|
# 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])))
|
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)
|
union_test = unittest.make(_union_test)
|
||||||
|
|
||||||
|
|
||||||
def _difference_test(ctx):
|
def _difference_test(ctx):
|
||||||
"""Unit tests for new_sets.difference."""
|
"""Unit tests for new_sets.difference."""
|
||||||
env = unittest.begin(ctx)
|
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()))
|
||||||
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(), 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([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])))
|
||||||
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(), 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([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([1]), new_sets.make(depset([1]))))
|
||||||
|
|
||||||
# If passing a list, verify that duplicate elements are ignored.
|
# 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])))
|
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)
|
difference_test = unittest.make(_difference_test)
|
||||||
|
|
||||||
|
|
||||||
def _to_list_test(ctx):
|
def _to_list_test(ctx):
|
||||||
"""Unit tests for new_sets.to_list."""
|
"""Unit tests for new_sets.to_list."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.equals(env, [], new_sets.to_list(new_sets.make()))
|
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], 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, [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)
|
to_list_test = unittest.make(_to_list_test)
|
||||||
|
|
||||||
|
|
||||||
def _make_test(ctx):
|
def _make_test(ctx):
|
||||||
"""Unit tests for new_sets.make."""
|
"""Unit tests for new_sets.make."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.equals(env, {}, new_sets.make()._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, {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, {1: None, 2: None}, new_sets.make(depset([1, 2]))._values)
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
make_test = unittest.make(_make_test)
|
make_test = unittest.make(_make_test)
|
||||||
|
|
||||||
|
|
||||||
def _copy_test(ctx):
|
def _copy_test(ctx):
|
||||||
"""Unit tests for new_sets.copy."""
|
"""Unit tests for new_sets.copy."""
|
||||||
env = unittest.begin(ctx)
|
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()), new_sets.make())
|
||||||
asserts.new_set_equals(env, new_sets.copy(new_sets.make([1, 2, 3])), new_sets.make([1, 2, 3]))
|
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))
|
|
||||||
|
|
||||||
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)
|
copy_test = unittest.make(_copy_test)
|
||||||
|
|
||||||
|
|
||||||
def _insert_test(ctx):
|
def _insert_test(ctx):
|
||||||
"""Unit tests for new_sets.insert."""
|
"""Unit tests for new_sets.insert."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.new_set_equals(env, new_sets.make([1, 2, 3]), new_sets.insert(new_sets.make([1, 2]), 3))
|
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).")
|
|
||||||
|
|
||||||
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)
|
insert_test = unittest.make(_insert_test)
|
||||||
|
|
||||||
|
|
||||||
def _contains_test(ctx):
|
def _contains_test(ctx):
|
||||||
"""Unit tests for new_sets.contains."""
|
"""Unit tests for new_sets.contains."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.false(env, new_sets.contains(new_sets.make(), 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]), 1))
|
||||||
asserts.true(env, new_sets.contains(new_sets.make([1, 2]), 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([2, 3]), 1))
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
contains_test = unittest.make(_contains_test)
|
contains_test = unittest.make(_contains_test)
|
||||||
|
|
||||||
|
|
||||||
def _length_test(ctx):
|
def _length_test(ctx):
|
||||||
"""Unit test for new_sets.length."""
|
"""Unit test for new_sets.length."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.equals(env, 0, new_sets.length(new_sets.make()))
|
asserts.equals(env, 0, new_sets.length(new_sets.make()))
|
||||||
asserts.equals(env, 1, new_sets.length(new_sets.make([1])))
|
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, 2, new_sets.length(new_sets.make([1, 2])))
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
length_test = unittest.make(_length_test)
|
length_test = unittest.make(_length_test)
|
||||||
|
|
||||||
|
|
||||||
def _remove_test(ctx):
|
def _remove_test(ctx):
|
||||||
"""Unit test for new_sets.remove."""
|
"""Unit test for new_sets.remove."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.new_set_equals(env, new_sets.make([1, 2]), new_sets.remove(new_sets.make([1, 2, 3]), 3))
|
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)
|
|
||||||
|
|
||||||
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)
|
remove_test = unittest.make(_remove_test)
|
||||||
|
|
||||||
|
|
||||||
def _repr_str_test(ctx):
|
def _repr_str_test(ctx):
|
||||||
"""Unit test for new_sets.repr and new_sets.str."""
|
"""Unit test for new_sets.repr and new_sets.str."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.equals(env, "[]", new_sets.repr(new_sets.make()))
|
asserts.equals(env, "[]", new_sets.repr(new_sets.make()))
|
||||||
asserts.equals(env, "[1]", new_sets.repr(new_sets.make([1])))
|
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, "[1, 2]", new_sets.repr(new_sets.make([1, 2])))
|
||||||
|
|
||||||
asserts.equals(env, "[]", new_sets.str(new_sets.make()))
|
asserts.equals(env, "[]", new_sets.str(new_sets.make()))
|
||||||
asserts.equals(env, "[1]", new_sets.str(new_sets.make([1])))
|
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, "[1, 2]", new_sets.str(new_sets.make([1, 2])))
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
repr_str_test = unittest.make(_repr_str_test)
|
repr_str_test = unittest.make(_repr_str_test)
|
||||||
|
|
||||||
|
|
||||||
def new_sets_test_suite():
|
def new_sets_test_suite():
|
||||||
"""Creates the test targets and test suite for new_sets.bzl tests."""
|
"""Creates the test targets and test suite for new_sets.bzl tests."""
|
||||||
unittest.suite(
|
unittest.suite(
|
||||||
"new_sets_tests",
|
"new_sets_tests",
|
||||||
disjoint_test,
|
disjoint_test,
|
||||||
intersection_test,
|
intersection_test,
|
||||||
is_equal_test,
|
is_equal_test,
|
||||||
is_subset_test,
|
is_subset_test,
|
||||||
difference_test,
|
difference_test,
|
||||||
union_test,
|
union_test,
|
||||||
to_list_test,
|
to_list_test,
|
||||||
make_test,
|
make_test,
|
||||||
copy_test,
|
copy_test,
|
||||||
insert_test,
|
insert_test,
|
||||||
contains_test,
|
contains_test,
|
||||||
length_test,
|
length_test,
|
||||||
remove_test,
|
remove_test,
|
||||||
repr_str_test,
|
repr_str_test,
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,72 +14,70 @@
|
||||||
|
|
||||||
"""Unit tests for partial.bzl."""
|
"""Unit tests for partial.bzl."""
|
||||||
|
|
||||||
load("//:lib.bzl", "partial", "asserts", "unittest")
|
load("//:lib.bzl", "asserts", "partial", "unittest")
|
||||||
|
|
||||||
|
|
||||||
def _make_noargs_nokwargs():
|
def _make_noargs_nokwargs():
|
||||||
"""Test utility for no args no kwargs case"""
|
"""Test utility for no args no kwargs case"""
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
def _make_args_nokwargs(arg1, arg2, arg3):
|
def _make_args_nokwargs(arg1, arg2, arg3):
|
||||||
"""Test utility for args no kwargs case"""
|
"""Test utility for args no kwargs case"""
|
||||||
return arg1 + arg2 + arg3
|
return arg1 + arg2 + arg3
|
||||||
|
|
||||||
def _make_args_kwargs(arg1, arg2, arg3, **kwargs):
|
def _make_args_kwargs(arg1, arg2, arg3, **kwargs):
|
||||||
"""Test utility for args and kwargs case"""
|
"""Test utility for args and kwargs case"""
|
||||||
return arg1 + arg2 + arg3 + kwargs["x"] + kwargs["y"]
|
return arg1 + arg2 + arg3 + kwargs["x"] + kwargs["y"]
|
||||||
|
|
||||||
def _call_noargs_nokwargs(call_arg1):
|
def _call_noargs_nokwargs(call_arg1):
|
||||||
"""Test utility no args no kwargs case where values passed from call site"""
|
"""Test utility no args no kwargs case where values passed from call site"""
|
||||||
return call_arg1;
|
return call_arg1
|
||||||
|
|
||||||
def _call_args_nokwargs(func_arg1, call_arg1):
|
def _call_args_nokwargs(func_arg1, call_arg1):
|
||||||
"""Test utility for args no kwargs case where values passed from call site"""
|
"""Test utility for args no kwargs case where values passed from call site"""
|
||||||
return func_arg1 + call_arg1;
|
return func_arg1 + call_arg1
|
||||||
|
|
||||||
def _call_args_kwargs(func_arg1, call_arg1, func_mult, call_mult):
|
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"""
|
"""Test utility for args and kwargs case where values passed from call site"""
|
||||||
return (func_arg1 + call_arg1) * func_mult * call_mult;
|
return (func_arg1 + call_arg1) * func_mult * call_mult
|
||||||
|
|
||||||
def _make_call_test(ctx):
|
def _make_call_test(ctx):
|
||||||
"""Unit tests for partial.make and partial.call."""
|
"""Unit tests for partial.make and partial.call."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
# Test cases where there are no args (or kwargs) at the make site, only
|
# Test cases where there are no args (or kwargs) at the make site, only
|
||||||
# at the call site.
|
# at the call site.
|
||||||
foo = partial.make(_make_noargs_nokwargs)
|
foo = partial.make(_make_noargs_nokwargs)
|
||||||
asserts.equals(env, 1, partial.call(foo))
|
asserts.equals(env, 1, partial.call(foo))
|
||||||
|
|
||||||
foo = partial.make(_make_args_nokwargs)
|
foo = partial.make(_make_args_nokwargs)
|
||||||
asserts.equals(env, 6, partial.call(foo, 1, 2, 3))
|
asserts.equals(env, 6, partial.call(foo, 1, 2, 3))
|
||||||
|
|
||||||
foo = partial.make(_make_args_kwargs)
|
foo = partial.make(_make_args_kwargs)
|
||||||
asserts.equals(env, 15, partial.call(foo, 1, 2, 3, x=4, y=5))
|
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
|
# Test cases where there are args (and/or kwargs) at the make site and the
|
||||||
# call site.
|
# call site.
|
||||||
foo = partial.make(_call_noargs_nokwargs, 100)
|
foo = partial.make(_call_noargs_nokwargs, 100)
|
||||||
asserts.equals(env, 100, partial.call(foo))
|
asserts.equals(env, 100, partial.call(foo))
|
||||||
|
|
||||||
foo = partial.make(_call_args_nokwargs, 100)
|
foo = partial.make(_call_args_nokwargs, 100)
|
||||||
asserts.equals(env, 112, partial.call(foo, 12))
|
asserts.equals(env, 112, partial.call(foo, 12))
|
||||||
|
|
||||||
foo = partial.make(_call_args_kwargs, 100, func_mult=10)
|
foo = partial.make(_call_args_kwargs, 100, func_mult = 10)
|
||||||
asserts.equals(env, 2240, partial.call(foo, 12, call_mult=2))
|
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
|
# Test case where there are args and kwargs ath the make site, and the call
|
||||||
# site overrides some make site args.
|
# site overrides some make site args.
|
||||||
foo = partial.make(_call_args_kwargs, 100, func_mult=10)
|
foo = partial.make(_call_args_kwargs, 100, func_mult = 10)
|
||||||
asserts.equals(env, 1120, partial.call(foo, 12, func_mult=5, call_mult=2))
|
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)
|
make_call_test = unittest.make(_make_call_test)
|
||||||
|
|
||||||
|
|
||||||
def partial_test_suite():
|
def partial_test_suite():
|
||||||
"""Creates the test targets and test suite for partial.bzl tests."""
|
"""Creates the test targets and test suite for partial.bzl tests."""
|
||||||
unittest.suite(
|
unittest.suite(
|
||||||
"partial_tests",
|
"partial_tests",
|
||||||
make_call_test,
|
make_call_test,
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,271 +14,271 @@
|
||||||
|
|
||||||
"""Unit tests for paths.bzl."""
|
"""Unit tests for paths.bzl."""
|
||||||
|
|
||||||
load("//:lib.bzl", "paths", "asserts", "unittest")
|
load("//:lib.bzl", "asserts", "paths", "unittest")
|
||||||
|
|
||||||
|
|
||||||
def _basename_test(ctx):
|
def _basename_test(ctx):
|
||||||
"""Unit tests for paths.basename."""
|
"""Unit tests for paths.basename."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
# Verify some degenerate cases.
|
# Verify some degenerate cases.
|
||||||
asserts.equals(env, "", paths.basename(""))
|
asserts.equals(env, "", paths.basename(""))
|
||||||
asserts.equals(env, "", paths.basename("/"))
|
asserts.equals(env, "", paths.basename("/"))
|
||||||
asserts.equals(env, "bar", paths.basename("foo///bar"))
|
asserts.equals(env, "bar", paths.basename("foo///bar"))
|
||||||
|
|
||||||
# Verify some realistic cases.
|
# Verify some realistic cases.
|
||||||
asserts.equals(env, "foo", paths.basename("foo"))
|
asserts.equals(env, "foo", paths.basename("foo"))
|
||||||
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"))
|
||||||
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,
|
# Verify that we correctly duplicate Python's os.path.basename behavior,
|
||||||
# where a trailing slash means the basename is empty.
|
# where a trailing slash means the basename is empty.
|
||||||
asserts.equals(env, "", paths.basename("foo/"))
|
asserts.equals(env, "", paths.basename("foo/"))
|
||||||
asserts.equals(env, "", paths.basename("/foo/"))
|
asserts.equals(env, "", paths.basename("/foo/"))
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
basename_test = unittest.make(_basename_test)
|
basename_test = unittest.make(_basename_test)
|
||||||
|
|
||||||
|
|
||||||
def _dirname_test(ctx):
|
def _dirname_test(ctx):
|
||||||
"""Unit tests for paths.dirname."""
|
"""Unit tests for paths.dirname."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
# Verify some degenerate cases.
|
# Verify some degenerate cases.
|
||||||
asserts.equals(env, "", paths.dirname(""))
|
asserts.equals(env, "", paths.dirname(""))
|
||||||
asserts.equals(env, "/", paths.dirname("/"))
|
asserts.equals(env, "/", paths.dirname("/"))
|
||||||
asserts.equals(env, "foo", paths.dirname("foo///bar"))
|
asserts.equals(env, "foo", paths.dirname("foo///bar"))
|
||||||
|
|
||||||
# Verify some realistic cases.
|
# Verify some realistic cases.
|
||||||
asserts.equals(env, "", paths.dirname("foo"))
|
asserts.equals(env, "", paths.dirname("foo"))
|
||||||
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"))
|
||||||
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,
|
# Verify that we correctly duplicate Python's os.path.dirname behavior,
|
||||||
# where a trailing slash means the dirname is the same as the original
|
# where a trailing slash means the dirname is the same as the original
|
||||||
# path (without the trailing slash).
|
# path (without the trailing slash).
|
||||||
asserts.equals(env, "foo", paths.dirname("foo/"))
|
asserts.equals(env, "foo", paths.dirname("foo/"))
|
||||||
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)
|
dirname_test = unittest.make(_dirname_test)
|
||||||
|
|
||||||
|
|
||||||
def _is_absolute_test(ctx):
|
def _is_absolute_test(ctx):
|
||||||
"""Unit tests for paths.is_absolute."""
|
"""Unit tests for paths.is_absolute."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
# Try a degenerate case.
|
# Try a degenerate case.
|
||||||
asserts.false(env, paths.is_absolute(""))
|
asserts.false(env, paths.is_absolute(""))
|
||||||
|
|
||||||
# Try some relative paths.
|
# 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/"))
|
asserts.false(env, paths.is_absolute("foo/"))
|
||||||
asserts.false(env, paths.is_absolute("foo/bar"))
|
asserts.false(env, paths.is_absolute("foo/bar"))
|
||||||
|
|
||||||
# Try some absolute paths.
|
# Try some absolute paths.
|
||||||
asserts.true(env, paths.is_absolute("/"))
|
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/"))
|
asserts.true(env, paths.is_absolute("/foo/"))
|
||||||
asserts.true(env, paths.is_absolute("/foo/bar"))
|
asserts.true(env, paths.is_absolute("/foo/bar"))
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
is_absolute_test = unittest.make(_is_absolute_test)
|
is_absolute_test = unittest.make(_is_absolute_test)
|
||||||
|
|
||||||
|
|
||||||
def _join_test(ctx):
|
def _join_test(ctx):
|
||||||
"""Unit tests for paths.join."""
|
"""Unit tests for paths.join."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
# Try a degenerate case.
|
# Try a degenerate case.
|
||||||
asserts.equals(env, "", paths.join(""))
|
asserts.equals(env, "", paths.join(""))
|
||||||
|
|
||||||
# Try some basic paths.
|
# Try some basic paths.
|
||||||
asserts.equals(env, "foo", paths.join("foo"))
|
asserts.equals(env, "foo", paths.join("foo"))
|
||||||
asserts.equals(env, "foo/bar", paths.join("foo", "bar"))
|
asserts.equals(env, "foo/bar", paths.join("foo", "bar"))
|
||||||
asserts.equals(env, "foo/bar/baz", paths.join("foo", "bar", "baz"))
|
asserts.equals(env, "foo/bar/baz", paths.join("foo", "bar", "baz"))
|
||||||
|
|
||||||
# Make sure an initially absolute path stays absolute.
|
# Make sure an initially absolute path stays absolute.
|
||||||
asserts.equals(env, "/foo", paths.join("/foo"))
|
asserts.equals(env, "/foo", paths.join("/foo"))
|
||||||
asserts.equals(env, "/foo/bar", paths.join("/foo", "bar"))
|
asserts.equals(env, "/foo/bar", paths.join("/foo", "bar"))
|
||||||
|
|
||||||
# Make sure an absolute path later in the list resets the result.
|
# 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, "/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/baz", paths.join("foo", "/bar", "baz"))
|
||||||
asserts.equals(env, "/bar", paths.join("/foo", "/bar"))
|
asserts.equals(env, "/bar", paths.join("/foo", "/bar"))
|
||||||
|
|
||||||
# Make sure a leading empty segment doesn't make it absolute.
|
# Make sure a leading empty segment doesn't make it absolute.
|
||||||
asserts.equals(env, "foo", paths.join("", "foo"))
|
asserts.equals(env, "foo", paths.join("", "foo"))
|
||||||
|
|
||||||
# Try some trailing slash scenarios.
|
# 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/", 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/"))
|
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.
|
# 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", paths.join("", "", "foo"))
|
asserts.equals(env, "foo", paths.join("", "", "foo"))
|
||||||
asserts.equals(env, "foo/bar", paths.join("foo", "", "", "bar"))
|
asserts.equals(env, "foo/bar", paths.join("foo", "", "", "bar"))
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
join_test = unittest.make(_join_test)
|
join_test = unittest.make(_join_test)
|
||||||
|
|
||||||
|
|
||||||
def _normalize_test(ctx):
|
def _normalize_test(ctx):
|
||||||
"""Unit tests for paths.normalize."""
|
"""Unit tests for paths.normalize."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
# Try the most basic case.
|
# Try the most basic case.
|
||||||
asserts.equals(env, ".", paths.normalize(""))
|
asserts.equals(env, ".", paths.normalize(""))
|
||||||
|
|
||||||
# Try some basic adjacent-slash removal.
|
# Try some basic adjacent-slash 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, "foo/bar", paths.normalize("foo////bar"))
|
||||||
|
|
||||||
# Try some "." removal.
|
# 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, "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("/."))
|
asserts.equals(env, "/", paths.normalize("/."))
|
||||||
|
|
||||||
# Try some ".." removal.
|
# Try some ".." removal.
|
||||||
asserts.equals(env, "bar", paths.normalize("foo/../bar"))
|
asserts.equals(env, "bar", paths.normalize("foo/../bar"))
|
||||||
asserts.equals(env, "foo", paths.normalize("foo/bar/.."))
|
asserts.equals(env, "foo", paths.normalize("foo/bar/.."))
|
||||||
asserts.equals(env, ".", paths.normalize("foo/.."))
|
asserts.equals(env, ".", paths.normalize("foo/.."))
|
||||||
asserts.equals(env, ".", paths.normalize("foo/bar/../.."))
|
asserts.equals(env, ".", paths.normalize("foo/bar/../.."))
|
||||||
asserts.equals(env, "..", paths.normalize("foo/../.."))
|
asserts.equals(env, "..", paths.normalize("foo/../.."))
|
||||||
asserts.equals(env, "/", paths.normalize("/foo/../.."))
|
asserts.equals(env, "/", paths.normalize("/foo/../.."))
|
||||||
asserts.equals(env, "../../c", paths.normalize("a/b/../../../../c/d/.."))
|
asserts.equals(env, "../../c", paths.normalize("a/b/../../../../c/d/.."))
|
||||||
|
|
||||||
# Make sure one or two initial slashes are preserved, but three or more are
|
# Make sure one or two initial slashes are preserved, but three or more are
|
||||||
# collapsed to a single slash.
|
# 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"))
|
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
|
# Trailing slashes should be removed unless the entire path is a trailing
|
||||||
# slash.
|
# slash.
|
||||||
asserts.equals(env, "/", paths.normalize("/"))
|
asserts.equals(env, "/", paths.normalize("/"))
|
||||||
asserts.equals(env, "foo", paths.normalize("foo/"))
|
asserts.equals(env, "foo", paths.normalize("foo/"))
|
||||||
asserts.equals(env, "foo/bar", paths.normalize("foo/bar/"))
|
asserts.equals(env, "foo/bar", paths.normalize("foo/bar/"))
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
normalize_test = unittest.make(_normalize_test)
|
normalize_test = unittest.make(_normalize_test)
|
||||||
|
|
||||||
|
|
||||||
def _relativize_test(ctx):
|
def _relativize_test(ctx):
|
||||||
"""Unit tests for paths.relativize."""
|
"""Unit tests for paths.relativize."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
# Make sure that relative-to-current-directory works in all forms.
|
# 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", ""))
|
||||||
asserts.equals(env, "foo", paths.relativize("foo", "."))
|
asserts.equals(env, "foo", paths.relativize("foo", "."))
|
||||||
|
|
||||||
# Try some regular cases.
|
# Try some regular cases.
|
||||||
asserts.equals(env, "bar", paths.relativize("foo/bar", "foo"))
|
asserts.equals(env, "bar", paths.relativize("foo/bar", "foo"))
|
||||||
asserts.equals(env, "baz", paths.relativize("foo/bar/baz", "foo/bar"))
|
asserts.equals(env, "baz", paths.relativize("foo/bar/baz", "foo/bar"))
|
||||||
asserts.equals(env, "bar/baz", paths.relativize("foo/bar/baz", "foo"))
|
asserts.equals(env, "bar/baz", paths.relativize("foo/bar/baz", "foo"))
|
||||||
|
|
||||||
# Try a case where a parent directory is normalized away.
|
# Try a case where a parent directory is normalized away.
|
||||||
asserts.equals(env, "baz", paths.relativize("foo/bar/../baz", "foo"))
|
asserts.equals(env, "baz", paths.relativize("foo/bar/../baz", "foo"))
|
||||||
|
|
||||||
# Relative paths work, as long as they share a common start.
|
# 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, "file", paths.relativize("../foo/bar/baz/file", "../foo/bar/baz"))
|
||||||
asserts.equals(env, "baz/file", paths.relativize("../foo/bar/baz/file", "../foo/bar"))
|
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)
|
relativize_test = unittest.make(_relativize_test)
|
||||||
|
|
||||||
|
|
||||||
def _replace_extension_test(ctx):
|
def _replace_extension_test(ctx):
|
||||||
"""Unit tests for paths.replace_extension."""
|
"""Unit tests for paths.replace_extension."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
# Try some degenerate cases.
|
# Try some degenerate cases.
|
||||||
asserts.equals(env, ".foo", paths.replace_extension("", ".foo"))
|
asserts.equals(env, ".foo", paths.replace_extension("", ".foo"))
|
||||||
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"))
|
asserts.equals(env, "foo.bar", paths.replace_extension("foo", ".bar"))
|
||||||
|
|
||||||
# Try a directory with an extension and basename that doesn't have one.
|
# Try a directory with an extension and basename that doesn't have one.
|
||||||
asserts.equals(env, "foo.bar/baz.quux",
|
asserts.equals(
|
||||||
paths.replace_extension("foo.bar/baz", ".quux"))
|
env,
|
||||||
|
"foo.bar/baz.quux",
|
||||||
|
paths.replace_extension("foo.bar/baz", ".quux"),
|
||||||
|
)
|
||||||
|
|
||||||
# Now try some things with legit extensions.
|
# Now try some things with legit extensions.
|
||||||
asserts.equals(env, "a.z", paths.replace_extension("a.b", ".z"))
|
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.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/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/b.z", paths.replace_extension(".a/b.c", ".z"))
|
||||||
asserts.equals(env, ".a.z", paths.replace_extension(".a.b", ".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.
|
# 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"))
|
asserts.equals(env, "foobaz", paths.replace_extension("foo.bar", "baz"))
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
replace_extension_test = unittest.make(_replace_extension_test)
|
replace_extension_test = unittest.make(_replace_extension_test)
|
||||||
|
|
||||||
|
|
||||||
def _split_extension_test(ctx):
|
def _split_extension_test(ctx):
|
||||||
"""Unit tests for paths.split_extension."""
|
"""Unit tests for paths.split_extension."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
# Try some degenerate cases.
|
# Try some degenerate cases.
|
||||||
asserts.equals(env, ("", ""), paths.split_extension(""))
|
asserts.equals(env, ("", ""), paths.split_extension(""))
|
||||||
asserts.equals(env, ("/", ""), paths.split_extension("/"))
|
asserts.equals(env, ("/", ""), paths.split_extension("/"))
|
||||||
asserts.equals(env, ("foo", ""), paths.split_extension("foo"))
|
asserts.equals(env, ("foo", ""), paths.split_extension("foo"))
|
||||||
|
|
||||||
# Try some paths whose basenames start with ".".
|
# Try some paths whose basenames start with ".".
|
||||||
asserts.equals(env, (".", ""), paths.split_extension("."))
|
asserts.equals(env, (".", ""), paths.split_extension("."))
|
||||||
asserts.equals(env, (".bashrc", ""), paths.split_extension(".bashrc"))
|
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"))
|
||||||
asserts.equals(env, (".foo/.bashrc", ""),
|
asserts.equals(
|
||||||
paths.split_extension(".foo/.bashrc"))
|
env,
|
||||||
|
(".foo/.bashrc", ""),
|
||||||
|
paths.split_extension(".foo/.bashrc"),
|
||||||
|
)
|
||||||
|
|
||||||
# Try some directories with extensions with basenames that don't have one.
|
# 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/baz", ""), paths.split_extension("foo.bar/baz"))
|
||||||
asserts.equals(env, ("foo.bar/.bashrc", ""),
|
asserts.equals(
|
||||||
paths.split_extension("foo.bar/.bashrc"))
|
env,
|
||||||
|
("foo.bar/.bashrc", ""),
|
||||||
|
paths.split_extension("foo.bar/.bashrc"),
|
||||||
|
)
|
||||||
|
|
||||||
# Now try some things that will actually get split.
|
# Now try some things that will actually get split.
|
||||||
asserts.equals(env, ("a", ".b"), paths.split_extension("a.b"))
|
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"), 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", ".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", ".c"), paths.split_extension(".a/b.c"))
|
||||||
asserts.equals(env, (".a", ".b"), paths.split_extension(".a.b"))
|
asserts.equals(env, (".a", ".b"), paths.split_extension(".a.b"))
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
split_extension_test = unittest.make(_split_extension_test)
|
split_extension_test = unittest.make(_split_extension_test)
|
||||||
|
|
||||||
|
|
||||||
def paths_test_suite():
|
def paths_test_suite():
|
||||||
"""Creates the test targets and test suite for paths.bzl tests."""
|
"""Creates the test targets and test suite for paths.bzl tests."""
|
||||||
unittest.suite(
|
unittest.suite(
|
||||||
"paths_tests",
|
"paths_tests",
|
||||||
basename_test,
|
basename_test,
|
||||||
dirname_test,
|
dirname_test,
|
||||||
is_absolute_test,
|
is_absolute_test,
|
||||||
join_test,
|
join_test,
|
||||||
normalize_test,
|
normalize_test,
|
||||||
relativize_test,
|
relativize_test,
|
||||||
replace_extension_test,
|
replace_extension_test,
|
||||||
split_extension_test,
|
split_extension_test,
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,40 +14,51 @@
|
||||||
|
|
||||||
"""Unit tests for selects.bzl."""
|
"""Unit tests for selects.bzl."""
|
||||||
|
|
||||||
load("//:lib.bzl", "selects", "asserts", "unittest")
|
load("//:lib.bzl", "asserts", "selects", "unittest")
|
||||||
|
|
||||||
|
|
||||||
def _with_or_test(ctx):
|
def _with_or_test(ctx):
|
||||||
"""Unit tests for with_or."""
|
"""Unit tests for with_or."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
# We actually test on with_or_dict because Skylark can't get the
|
# We actually test on with_or_dict because Skylark can't get the
|
||||||
# dictionary from a select().
|
# dictionary from a select().
|
||||||
|
|
||||||
# Test select()-compatible input syntax.
|
# Test select()-compatible input syntax.
|
||||||
input_dict = {":foo": ":d1", "//conditions:default": ":d1"}
|
input_dict = {":foo": ":d1", "//conditions:default": ":d1"}
|
||||||
asserts.equals(env, input_dict, selects.with_or_dict(input_dict))
|
asserts.equals(env, input_dict, selects.with_or_dict(input_dict))
|
||||||
|
|
||||||
# Test OR syntax.
|
# Test OR syntax.
|
||||||
or_dict = {(":foo", ":bar"): ":d1"}
|
or_dict = {(":foo", ":bar"): ":d1"}
|
||||||
asserts.equals(env, {":foo": ":d1", ":bar": ":d1"},
|
asserts.equals(
|
||||||
selects.with_or_dict(or_dict))
|
env,
|
||||||
|
{":foo": ":d1", ":bar": ":d1"},
|
||||||
|
selects.with_or_dict(or_dict),
|
||||||
|
)
|
||||||
|
|
||||||
# Test mixed syntax.
|
# Test mixed syntax.
|
||||||
mixed_dict = {":foo": ":d1", (":bar", ":baz"): ":d2",
|
mixed_dict = {
|
||||||
"//conditions:default": ":d3"}
|
":foo": ":d1",
|
||||||
asserts.equals(env, {":foo": ":d1", ":bar": ":d2", ":baz": ":d2",
|
(":bar", ":baz"): ":d2",
|
||||||
"//conditions:default": ":d3"},
|
"//conditions:default": ":d3",
|
||||||
selects.with_or_dict(mixed_dict))
|
}
|
||||||
|
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)
|
with_or_test = unittest.make(_with_or_test)
|
||||||
|
|
||||||
|
|
||||||
def selects_test_suite():
|
def selects_test_suite():
|
||||||
"""Creates the test targets and test suite for selects.bzl tests."""
|
"""Creates the test targets and test suite for selects.bzl tests."""
|
||||||
unittest.suite(
|
unittest.suite(
|
||||||
"selects_tests",
|
"selects_tests",
|
||||||
with_or_test,
|
with_or_test,
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,146 +14,139 @@
|
||||||
|
|
||||||
"""Unit tests for sets.bzl."""
|
"""Unit tests for sets.bzl."""
|
||||||
|
|
||||||
load("//:lib.bzl", "sets", "asserts", "unittest")
|
load("//:lib.bzl", "asserts", "sets", "unittest")
|
||||||
|
|
||||||
|
|
||||||
def _is_equal_test(ctx):
|
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
|
# 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
|
# be inconclusive because they use `asserts.set_equals`, which in turn calls
|
||||||
# `sets.is_equal`.
|
# `sets.is_equal`.
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.true(env, sets.is_equal([], []))
|
asserts.true(env, sets.is_equal([], []))
|
||||||
asserts.false(env, sets.is_equal([], [1]))
|
asserts.false(env, sets.is_equal([], [1]))
|
||||||
asserts.false(env, sets.is_equal([1], []))
|
asserts.false(env, sets.is_equal([1], []))
|
||||||
asserts.true(env, sets.is_equal([1], [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], [1, 2]))
|
||||||
asserts.false(env, sets.is_equal([1], [2]))
|
asserts.false(env, sets.is_equal([1], [2]))
|
||||||
asserts.false(env, sets.is_equal([1], depset([1, 2])))
|
asserts.false(env, sets.is_equal([1], depset([1, 2])))
|
||||||
|
|
||||||
# Verify that the implementation is not using == on the sets directly.
|
# Verify that the implementation is not using == on the sets directly.
|
||||||
asserts.true(env, sets.is_equal(depset([1]), depset([1])))
|
asserts.true(env, sets.is_equal(depset([1]), depset([1])))
|
||||||
|
|
||||||
# If passing a list, verify that duplicate elements are ignored.
|
# If passing a list, verify that duplicate elements are ignored.
|
||||||
asserts.true(env, sets.is_equal([1, 1], [1]))
|
asserts.true(env, sets.is_equal([1, 1], [1]))
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
is_equal_test = unittest.make(_is_equal_test)
|
is_equal_test = unittest.make(_is_equal_test)
|
||||||
|
|
||||||
|
|
||||||
def _is_subset_test(ctx):
|
def _is_subset_test(ctx):
|
||||||
"""Unit tests for sets.is_subset."""
|
"""Unit tests for sets.is_subset."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.true(env, sets.is_subset([], []))
|
asserts.true(env, sets.is_subset([], []))
|
||||||
asserts.true(env, sets.is_subset([], [1]))
|
asserts.true(env, sets.is_subset([], [1]))
|
||||||
asserts.false(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]))
|
||||||
asserts.true(env, sets.is_subset([1], [1, 2]))
|
asserts.true(env, sets.is_subset([1], [1, 2]))
|
||||||
asserts.false(env, sets.is_subset([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([1], depset([1, 2])))
|
||||||
|
|
||||||
# If passing a list, verify that duplicate elements are ignored.
|
# If passing a list, verify that duplicate elements are ignored.
|
||||||
asserts.true(env, sets.is_subset([1, 1], [1, 2]))
|
asserts.true(env, sets.is_subset([1, 1], [1, 2]))
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
is_subset_test = unittest.make(_is_subset_test)
|
is_subset_test = unittest.make(_is_subset_test)
|
||||||
|
|
||||||
|
|
||||||
def _disjoint_test(ctx):
|
def _disjoint_test(ctx):
|
||||||
"""Unit tests for sets.disjoint."""
|
"""Unit tests for sets.disjoint."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.true(env, sets.disjoint([], []))
|
asserts.true(env, sets.disjoint([], []))
|
||||||
asserts.true(env, sets.disjoint([], [1]))
|
asserts.true(env, sets.disjoint([], [1]))
|
||||||
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]))
|
||||||
asserts.false(env, sets.disjoint([1], [1, 2]))
|
asserts.false(env, sets.disjoint([1], [1, 2]))
|
||||||
asserts.true(env, sets.disjoint([1], [2]))
|
asserts.true(env, sets.disjoint([1], [2]))
|
||||||
asserts.true(env, sets.disjoint([1], depset([2])))
|
asserts.true(env, sets.disjoint([1], depset([2])))
|
||||||
|
|
||||||
# If passing a list, verify that duplicate elements are ignored.
|
# If passing a list, verify that duplicate elements are ignored.
|
||||||
asserts.false(env, sets.disjoint([1, 1], [1, 2]))
|
asserts.false(env, sets.disjoint([1, 1], [1, 2]))
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
disjoint_test = unittest.make(_disjoint_test)
|
disjoint_test = unittest.make(_disjoint_test)
|
||||||
|
|
||||||
|
|
||||||
def _intersection_test(ctx):
|
def _intersection_test(ctx):
|
||||||
"""Unit tests for sets.intersection."""
|
"""Unit tests for sets.intersection."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.set_equals(env, [], sets.intersection([], []))
|
asserts.set_equals(env, [], sets.intersection([], []))
|
||||||
asserts.set_equals(env, [], sets.intersection([], [1]))
|
asserts.set_equals(env, [], sets.intersection([], [1]))
|
||||||
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]))
|
||||||
asserts.set_equals(env, [1], sets.intersection([1], [1, 2]))
|
asserts.set_equals(env, [1], sets.intersection([1], [1, 2]))
|
||||||
asserts.set_equals(env, [], sets.intersection([1], [2]))
|
asserts.set_equals(env, [], sets.intersection([1], [2]))
|
||||||
asserts.set_equals(env, [1], sets.intersection([1], depset([1])))
|
asserts.set_equals(env, [1], sets.intersection([1], depset([1])))
|
||||||
|
|
||||||
# If passing a list, verify that duplicate elements are ignored.
|
# If passing a list, verify that duplicate elements are ignored.
|
||||||
asserts.set_equals(env, [1], sets.intersection([1, 1], [1, 2]))
|
asserts.set_equals(env, [1], sets.intersection([1, 1], [1, 2]))
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
intersection_test = unittest.make(_intersection_test)
|
intersection_test = unittest.make(_intersection_test)
|
||||||
|
|
||||||
|
|
||||||
def _union_test(ctx):
|
def _union_test(ctx):
|
||||||
"""Unit tests for sets.union."""
|
"""Unit tests for sets.union."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.set_equals(env, [], sets.union())
|
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, [], sets.union([], []))
|
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], []))
|
asserts.set_equals(env, [1], sets.union([1], []))
|
||||||
asserts.set_equals(env, [1], sets.union([1], [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], [1, 2]))
|
||||||
asserts.set_equals(env, [1, 2], sets.union([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, [1], sets.union([1], depset([1])))
|
||||||
|
|
||||||
# If passing a list, verify that duplicate elements are ignored.
|
# If passing a list, verify that duplicate elements are ignored.
|
||||||
asserts.set_equals(env, [1, 2], sets.union([1, 1], [1, 2]))
|
asserts.set_equals(env, [1, 2], sets.union([1, 1], [1, 2]))
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
union_test = unittest.make(_union_test)
|
union_test = unittest.make(_union_test)
|
||||||
|
|
||||||
|
|
||||||
def _difference_test(ctx):
|
def _difference_test(ctx):
|
||||||
"""Unit tests for sets.difference."""
|
"""Unit tests for sets.difference."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.set_equals(env, [], sets.difference([], []))
|
asserts.set_equals(env, [], sets.difference([], []))
|
||||||
asserts.set_equals(env, [], sets.difference([], [1]))
|
asserts.set_equals(env, [], sets.difference([], [1]))
|
||||||
asserts.set_equals(env, [1], 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]))
|
||||||
asserts.set_equals(env, [], sets.difference([1], [1, 2]))
|
asserts.set_equals(env, [], sets.difference([1], [1, 2]))
|
||||||
asserts.set_equals(env, [1], sets.difference([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([1], depset([1])))
|
||||||
|
|
||||||
# If passing a list, verify that duplicate elements are ignored.
|
# If passing a list, verify that duplicate elements are ignored.
|
||||||
asserts.set_equals(env, [2], sets.difference([1, 2], [1, 1]))
|
asserts.set_equals(env, [2], sets.difference([1, 2], [1, 1]))
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
difference_test = unittest.make(_difference_test)
|
difference_test = unittest.make(_difference_test)
|
||||||
|
|
||||||
|
|
||||||
def sets_test_suite():
|
def sets_test_suite():
|
||||||
"""Creates the test targets and test suite for sets.bzl tests."""
|
"""Creates the test targets and test suite for sets.bzl tests."""
|
||||||
unittest.suite(
|
unittest.suite(
|
||||||
"sets_tests",
|
"sets_tests",
|
||||||
disjoint_test,
|
disjoint_test,
|
||||||
intersection_test,
|
intersection_test,
|
||||||
is_equal_test,
|
is_equal_test,
|
||||||
is_subset_test,
|
is_subset_test,
|
||||||
difference_test,
|
difference_test,
|
||||||
union_test,
|
union_test,
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,98 +14,94 @@
|
||||||
|
|
||||||
"""Unit tests for shell.bzl."""
|
"""Unit tests for shell.bzl."""
|
||||||
|
|
||||||
load("//:lib.bzl", "shell", "asserts", "unittest")
|
load("//:lib.bzl", "asserts", "shell", "unittest")
|
||||||
|
|
||||||
|
|
||||||
def _shell_array_literal_test(ctx):
|
def _shell_array_literal_test(ctx):
|
||||||
"""Unit tests for shell.array_literal."""
|
"""Unit tests for shell.array_literal."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.equals(env, "()", shell.array_literal([]))
|
asserts.equals(env, "()", shell.array_literal([]))
|
||||||
asserts.equals(env, "('1')", shell.array_literal([1]))
|
asserts.equals(env, "('1')", shell.array_literal([1]))
|
||||||
asserts.equals(env, "('1' '2' '3')", shell.array_literal([1, 2, 3]))
|
asserts.equals(env, "('1' '2' '3')", shell.array_literal([1, 2, 3]))
|
||||||
asserts.equals(env, "('$foo')", shell.array_literal(["$foo"]))
|
asserts.equals(env, "('$foo')", shell.array_literal(["$foo"]))
|
||||||
asserts.equals(env, "('qu\"o\"te')", shell.array_literal(['qu"o"te']))
|
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)
|
shell_array_literal_test = unittest.make(_shell_array_literal_test)
|
||||||
|
|
||||||
|
|
||||||
def _shell_quote_test(ctx):
|
def _shell_quote_test(ctx):
|
||||||
"""Unit tests for shell.quote."""
|
"""Unit tests for shell.quote."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.equals(env, "'foo'", shell.quote("foo"))
|
asserts.equals(env, "'foo'", shell.quote("foo"))
|
||||||
asserts.equals(env, "'foo bar'", shell.quote("foo bar"))
|
asserts.equals(env, "'foo bar'", shell.quote("foo bar"))
|
||||||
asserts.equals(env, "'three spaces'", shell.quote("three spaces"))
|
asserts.equals(env, "'three spaces'", shell.quote("three spaces"))
|
||||||
asserts.equals(env, "' leading'", shell.quote(" leading"))
|
asserts.equals(env, "' leading'", shell.quote(" leading"))
|
||||||
asserts.equals(env, "'trailing '", shell.quote("trailing "))
|
asserts.equals(env, "'trailing '", shell.quote("trailing "))
|
||||||
asserts.equals(env, "'new\nline'", shell.quote("new\nline"))
|
asserts.equals(env, "'new\nline'", shell.quote("new\nline"))
|
||||||
asserts.equals(env, "'tab\tcharacter'", shell.quote("tab\tcharacter"))
|
asserts.equals(env, "'tab\tcharacter'", shell.quote("tab\tcharacter"))
|
||||||
asserts.equals(env, "'$foo'", shell.quote("$foo"))
|
asserts.equals(env, "'$foo'", shell.quote("$foo"))
|
||||||
asserts.equals(env, "'qu\"o\"te'", shell.quote('qu"o"te'))
|
asserts.equals(env, "'qu\"o\"te'", shell.quote('qu"o"te'))
|
||||||
asserts.equals(env, "'it'\\''s'", shell.quote("it's"))
|
asserts.equals(env, "'it'\\''s'", shell.quote("it's"))
|
||||||
asserts.equals(env, "'foo\\bar'", shell.quote(r"foo\bar"))
|
asserts.equals(env, "'foo\\bar'", shell.quote("foo\\bar"))
|
||||||
asserts.equals(env, "'back`echo q`uote'", shell.quote(r"back`echo q`uote"))
|
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)
|
shell_quote_test = unittest.make(_shell_quote_test)
|
||||||
|
|
||||||
|
|
||||||
def _shell_spawn_e2e_test_impl(ctx):
|
def _shell_spawn_e2e_test_impl(ctx):
|
||||||
"""Test spawning a real shell."""
|
"""Test spawning a real shell."""
|
||||||
args = [
|
args = [
|
||||||
"foo",
|
"foo",
|
||||||
"foo bar",
|
"foo bar",
|
||||||
"three spaces",
|
"three spaces",
|
||||||
" leading",
|
" leading",
|
||||||
"trailing ",
|
"trailing ",
|
||||||
"new\nline",
|
"new\nline",
|
||||||
"tab\tcharacter",
|
"tab\tcharacter",
|
||||||
"$foo",
|
"$foo",
|
||||||
'qu"o"te',
|
'qu"o"te',
|
||||||
"it's",
|
"it's",
|
||||||
r"foo\bar",
|
"foo\\bar",
|
||||||
"back`echo q`uote",
|
"back`echo q`uote",
|
||||||
]
|
]
|
||||||
script_content = "\n".join([
|
script_content = "\n".join([
|
||||||
"#!/bin/bash",
|
"#!/bin/bash",
|
||||||
"myarray=" + shell.array_literal(args),
|
"myarray=" + shell.array_literal(args),
|
||||||
'output=$(echo "${myarray[@]}")',
|
'output=$(echo "${myarray[@]}")',
|
||||||
# For logging:
|
# For logging:
|
||||||
'echo "DEBUG: output=[${output}]" >&2',
|
'echo "DEBUG: output=[${output}]" >&2',
|
||||||
# The following is a shell representation of what the echo of the quoted
|
# 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
|
# array will look like. It looks a bit confusing considering it's shell
|
||||||
# quoted into Python. Shell using single quotes to minimize shell
|
# quoted into Python. Shell using single quotes to minimize shell
|
||||||
# escaping, so only the single quote needs to be escaped as '\'', all
|
# escaping, so only the single quote needs to be escaped as '\'', all
|
||||||
# others are essentially kept literally.
|
# others are essentially kept literally.
|
||||||
"expected='foo foo bar three spaces leading trailing new",
|
"expected='foo foo bar three spaces leading trailing new",
|
||||||
"line tab\tcharacter $foo qu\"o\"te it'\\''s foo\\bar back`echo q`uote'",
|
"line tab\tcharacter $foo qu\"o\"te it'\\''s foo\\bar back`echo q`uote'",
|
||||||
'[[ "${output}" == "${expected}" ]]',
|
'[[ "${output}" == "${expected}" ]]',
|
||||||
])
|
])
|
||||||
script_file = ctx.actions.declare_file("%s.sh" % (ctx.label.name))
|
script_file = ctx.actions.declare_file("%s.sh" % (ctx.label.name))
|
||||||
ctx.actions.write(
|
ctx.actions.write(
|
||||||
output = script_file,
|
output = script_file,
|
||||||
content = script_content,
|
content = script_content,
|
||||||
is_executable = True,
|
is_executable = True,
|
||||||
)
|
)
|
||||||
return [
|
return [
|
||||||
DefaultInfo(executable=script_file),
|
DefaultInfo(executable = script_file),
|
||||||
]
|
]
|
||||||
|
|
||||||
shell_spawn_e2e_test = rule(
|
shell_spawn_e2e_test = rule(
|
||||||
test = True,
|
test = True,
|
||||||
implementation = _shell_spawn_e2e_test_impl,
|
implementation = _shell_spawn_e2e_test_impl,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def shell_test_suite():
|
def shell_test_suite():
|
||||||
"""Creates the test targets and test suite for shell.bzl tests."""
|
"""Creates the test targets and test suite for shell.bzl tests."""
|
||||||
unittest.suite(
|
unittest.suite(
|
||||||
"shell_tests",
|
"shell_tests",
|
||||||
shell_array_literal_test,
|
shell_array_literal_test,
|
||||||
shell_quote_test,
|
shell_quote_test,
|
||||||
shell_spawn_e2e_test,
|
shell_spawn_e2e_test,
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,36 +14,40 @@
|
||||||
|
|
||||||
"""Unit tests for structs.bzl."""
|
"""Unit tests for structs.bzl."""
|
||||||
|
|
||||||
load("//:lib.bzl", "structs", "asserts", "unittest")
|
load("//:lib.bzl", "asserts", "structs", "unittest")
|
||||||
|
|
||||||
|
|
||||||
def _add_test(ctx):
|
def _add_test(ctx):
|
||||||
"""Unit tests for dicts.add."""
|
"""Unit tests for dicts.add."""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
# Test zero- and one-argument behavior.
|
# Test zero- and one-argument behavior.
|
||||||
asserts.equals(env, {}, structs.to_dict(struct()))
|
asserts.equals(env, {}, structs.to_dict(struct()))
|
||||||
asserts.equals(env, {"a": 1}, structs.to_dict(struct(a=1)))
|
asserts.equals(env, {"a": 1}, structs.to_dict(struct(a = 1)))
|
||||||
|
|
||||||
# Test simple two-argument behavior.
|
# Test simple two-argument behavior.
|
||||||
asserts.equals(env, {"a": 1, "b": 2}, structs.to_dict(struct(a=1, b=2)))
|
asserts.equals(env, {"a": 1, "b": 2}, structs.to_dict(struct(a = 1, b = 2)))
|
||||||
|
|
||||||
# Test simple more-than-two-argument behavior.
|
# Test simple more-than-two-argument behavior.
|
||||||
asserts.equals(env, {"a": 1, "b": 2, "c": 3, "d": 4},
|
asserts.equals(
|
||||||
structs.to_dict(struct(a=1, b=2, c=3, d=4)))
|
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.
|
# Test transformation is not applied transitively.
|
||||||
asserts.equals(env, {"a": 1, "b": struct(bb=1)},
|
asserts.equals(
|
||||||
structs.to_dict(struct(a=1, b=struct(bb=1))))
|
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)
|
add_test = unittest.make(_add_test)
|
||||||
|
|
||||||
|
|
||||||
def structs_test_suite():
|
def structs_test_suite():
|
||||||
"""Creates the test targets and test suite for structs.bzl tests."""
|
"""Creates the test targets and test suite for structs.bzl tests."""
|
||||||
unittest.suite(
|
unittest.suite(
|
||||||
"structs_tests",
|
"structs_tests",
|
||||||
add_test,
|
add_test,
|
||||||
)
|
)
|
||||||
|
|
|
@ -13,14 +13,12 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
"""Unit tests for types.bzl."""
|
"""Unit tests for types.bzl."""
|
||||||
|
|
||||||
load("//:lib.bzl", "types", "asserts", "unittest")
|
load("//:lib.bzl", "asserts", "types", "unittest")
|
||||||
|
|
||||||
|
|
||||||
def _a_function():
|
def _a_function():
|
||||||
"""A dummy function for testing."""
|
"""A dummy function for testing."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def _is_string_test(ctx):
|
def _is_string_test(ctx):
|
||||||
"""Unit tests for types.is_string."""
|
"""Unit tests for types.is_string."""
|
||||||
|
|
||||||
|
@ -39,10 +37,8 @@ def _is_string_test(ctx):
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
|
|
||||||
is_string_test = unittest.make(_is_string_test)
|
is_string_test = unittest.make(_is_string_test)
|
||||||
|
|
||||||
|
|
||||||
def _is_bool_test(ctx):
|
def _is_bool_test(ctx):
|
||||||
"""Unit tests for types.is_bool."""
|
"""Unit tests for types.is_bool."""
|
||||||
|
|
||||||
|
@ -61,10 +57,8 @@ def _is_bool_test(ctx):
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
|
|
||||||
is_bool_test = unittest.make(_is_bool_test)
|
is_bool_test = unittest.make(_is_bool_test)
|
||||||
|
|
||||||
|
|
||||||
def _is_list_test(ctx):
|
def _is_list_test(ctx):
|
||||||
"""Unit tests for types.is_list."""
|
"""Unit tests for types.is_list."""
|
||||||
|
|
||||||
|
@ -83,10 +77,8 @@ def _is_list_test(ctx):
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
|
|
||||||
is_list_test = unittest.make(_is_list_test)
|
is_list_test = unittest.make(_is_list_test)
|
||||||
|
|
||||||
|
|
||||||
def _is_none_test(ctx):
|
def _is_none_test(ctx):
|
||||||
"""Unit tests for types.is_none."""
|
"""Unit tests for types.is_none."""
|
||||||
|
|
||||||
|
@ -105,10 +97,8 @@ def _is_none_test(ctx):
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
|
|
||||||
is_none_test = unittest.make(_is_none_test)
|
is_none_test = unittest.make(_is_none_test)
|
||||||
|
|
||||||
|
|
||||||
def _is_int_test(ctx):
|
def _is_int_test(ctx):
|
||||||
"""Unit tests for types.is_int."""
|
"""Unit tests for types.is_int."""
|
||||||
|
|
||||||
|
@ -128,17 +118,15 @@ def _is_int_test(ctx):
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
|
|
||||||
is_int_test = unittest.make(_is_int_test)
|
is_int_test = unittest.make(_is_int_test)
|
||||||
|
|
||||||
|
|
||||||
def _is_tuple_test(ctx):
|
def _is_tuple_test(ctx):
|
||||||
"""Unit tests for types.is_tuple."""
|
"""Unit tests for types.is_tuple."""
|
||||||
|
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.true(env, types.is_tuple(()))
|
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(1))
|
||||||
asserts.false(env, types.is_tuple("s"))
|
asserts.false(env, types.is_tuple("s"))
|
||||||
|
@ -151,17 +139,15 @@ def _is_tuple_test(ctx):
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
|
|
||||||
is_tuple_test = unittest.make(_is_tuple_test)
|
is_tuple_test = unittest.make(_is_tuple_test)
|
||||||
|
|
||||||
|
|
||||||
def _is_dict_test(ctx):
|
def _is_dict_test(ctx):
|
||||||
"""Unit tests for types.is_dict."""
|
"""Unit tests for types.is_dict."""
|
||||||
|
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.true(env, types.is_dict({}))
|
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(1))
|
||||||
asserts.false(env, types.is_dict("s"))
|
asserts.false(env, types.is_dict("s"))
|
||||||
|
@ -174,10 +160,8 @@ def _is_dict_test(ctx):
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
|
|
||||||
is_dict_test = unittest.make(_is_dict_test)
|
is_dict_test = unittest.make(_is_dict_test)
|
||||||
|
|
||||||
|
|
||||||
def _is_function_test(ctx):
|
def _is_function_test(ctx):
|
||||||
"""Unit tests for types.is_dict."""
|
"""Unit tests for types.is_dict."""
|
||||||
|
|
||||||
|
@ -196,10 +180,8 @@ def _is_function_test(ctx):
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
|
|
||||||
is_function_test = unittest.make(_is_function_test)
|
is_function_test = unittest.make(_is_function_test)
|
||||||
|
|
||||||
|
|
||||||
def types_test_suite():
|
def types_test_suite():
|
||||||
"""Creates the test targets and test suite for types.bzl tests."""
|
"""Creates the test targets and test suite for types.bzl tests."""
|
||||||
unittest.suite(
|
unittest.suite(
|
||||||
|
|
|
@ -14,55 +14,55 @@
|
||||||
|
|
||||||
"""Unit tests for versions.bzl."""
|
"""Unit tests for versions.bzl."""
|
||||||
|
|
||||||
load("//:lib.bzl", "versions", "asserts", "unittest")
|
load("//:lib.bzl", "asserts", "unittest", "versions")
|
||||||
|
|
||||||
def _parse_test(ctx):
|
def _parse_test(ctx):
|
||||||
"""Unit tests for versions.parse"""
|
"""Unit tests for versions.parse"""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.equals(env, (0, 10, 0), versions.parse("0.10.0rc1 abcd123"))
|
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 abcd123"))
|
||||||
asserts.equals(env, (0, 4, 0), versions.parse("0.4.0"))
|
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, 4, 0), versions.parse("0.4.0rc"))
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
def _version_comparison_test(ctx):
|
def _version_comparison_test(ctx):
|
||||||
"""Unit tests for versions.is_at_least and is_at_most"""
|
"""Unit tests for versions.is_at_least and is_at_most"""
|
||||||
env = unittest.begin(ctx)
|
env = unittest.begin(ctx)
|
||||||
|
|
||||||
asserts.false(env, versions.is_at_least("0.11.0 123abcd", "0.10.0rc1 abcd123"))
|
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.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", "0.9.0rc3"))
|
||||||
asserts.true(env, versions.is_at_least("0.9.0", "1.2.3"))
|
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.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.3.0rc2"))
|
||||||
asserts.true(env, versions.is_at_most("0.4.0", "0.4.0rc3"))
|
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.true(env, versions.is_at_most("1.4.0", "0.4.0rc3"))
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
def _check_test(ctx):
|
def _check_test(ctx):
|
||||||
"""Unit tests for versions.check"""
|
"""Unit tests for versions.check"""
|
||||||
env = unittest.begin(ctx)
|
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 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.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", 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", maximum_bazel_version = "1.0.0", bazel_version = "0.10.0rc1 abcd123"))
|
||||||
|
|
||||||
unittest.end(env)
|
unittest.end(env)
|
||||||
|
|
||||||
parse_test = unittest.make(_parse_test)
|
parse_test = unittest.make(_parse_test)
|
||||||
version_comparison_test = unittest.make(_version_comparison_test)
|
version_comparison_test = unittest.make(_version_comparison_test)
|
||||||
check_test = unittest.make(_check_test)
|
check_test = unittest.make(_check_test)
|
||||||
|
|
||||||
def versions_test_suite():
|
def versions_test_suite():
|
||||||
"""Creates the test targets and test suite for versions.bzl tests."""
|
"""Creates the test targets and test suite for versions.bzl tests."""
|
||||||
unittest.suite(
|
unittest.suite(
|
||||||
"versions_tests",
|
"versions_tests",
|
||||||
parse_test,
|
parse_test,
|
||||||
version_comparison_test,
|
version_comparison_test,
|
||||||
check_test,
|
check_test,
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue