123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712 |
- # python3
- # Copyright 2021 The Chromium Authors. All rights reserved.
- # Use of this source code is governed by a BSD-style license that can be
- # found in the LICENSE file.
- from datetime import datetime
- import io
- import re
- import tempfile
- import toml
- import unittest
- from lib import gen
- from lib import cargo
- from lib import compiler
- # An example output from `cargo tree`
- # 1. We patch paths into the Cargo.toml files that we feed to `cargo tree` and
- # this demonstrates that for the "quote" crate by including the path there.
- # 2. We include features in the output, demonstrated by many deps here. And we
- # also have an example of a crate without any features with the second
- # occurrence of "unicode-xid".
- # 3. Some crates get de-duped and that means get a (*) on them, which we can
- # see.
- # 4. A proc-macro crate is a different kind of crate and is designated by the
- # (proc-macro) after the version, and we have an example of that with
- # cxxbridge-macro.
- # 5. We include direct deps as well as transitive deps, which have more than one
- # piece of ascii art on their line.
- CARGO_TREE = """
- cxx v1.0.56 (/path/to/chromium/src/third_party/rust/cxx/v1/crate)
- ├── cxxbridge-macro v1.0.56 (proc-macro)
- │ ├── proc-macro2 v1.0.32 default,proc-macro,span-locations
- │ │ └── unicode-xid v0.2.2 default
- │ ├── quote v1.0.10 (/path/to/chromium/src/third_party/rust/quote/v1/crate) default,proc-macro
- │ │ └── proc-macro2 v1.0.32 default,proc-macro,span-locations (*)
- │ └── syn v1.0.81 clone-impls,default,derive,full,parsing,printing,proc-macro,quote
- │ ├── proc-macro2 v1.0.32 default,proc-macro,span-locations (*)
- │ ├── quote v1.0.10 default,proc-macro (*)
- │ └── unicode-xid v0.2.2
- └── link-cplusplus v1.0.5 default
- """.lstrip("\n")
- class GenTestCase(unittest.TestCase):
- def assertListSortedEqual(self, a, b, msg=None):
- a.sort()
- b.sort()
- if msg:
- self.assertListEqual(a, b, msg=msg)
- else:
- self.assertListEqual(a, b)
- def matching_archs(self, matching: str) -> set[str]:
- return {
- arch
- for arch in compiler._RUSTC_ARCH_TO_BUILD_CONDITION
- if re.search(matching, arch)
- }
- def all_archs(self):
- return set(compiler._RUSTC_ARCH_TO_BUILD_CONDITION.keys())
- def make_args(self):
- class Args:
- pass
- args = Args
- args.verbose = False
- return args
- def test_parse_cargo_tree_dependency_line(self):
- args = self.make_args()
- lines = CARGO_TREE.split("\n")
- # Here we are simulating `cargo tree` on a third-party Cargo.toml file,
- # not our special third_party.toml file. So we pass False as
- # is_third_party_toml, and we can give an empty parsed toml file as it
- # won't be used then.
- # cxx v1.0.56 (/path/to/chromium/src/third_party/rust/cxx/v1/crate)
- r = gen._parse_cargo_tree_dependency_line(args, dict(), False, lines[0])
- self.assertEqual(r, None) # not a dependency
- # ├── cxxbridge-macro v1.0.56 (proc-macro)
- r = gen._parse_cargo_tree_dependency_line(args, dict(), False, lines[1])
- expected = gen.CargoTreeDependency(cargo.CrateKey(
- "cxxbridge-macro", "1.0.56"),
- full_version="1.0.56")
- self.assertEqual(r, expected)
- # │ ├── proc-macro2 v1.0.32 default,proc-macro,span-locations
- r = gen._parse_cargo_tree_dependency_line(args, dict(), False, lines[2])
- expected = gen.CargoTreeDependency(
- cargo.CrateKey("proc-macro2", "1.0.32"),
- full_version="1.0.32",
- features=["default", "proc-macro", "span-locations"])
- self.assertEqual(r, expected)
- # │ │ └── unicode-xid v0.2.2 default
- r = gen._parse_cargo_tree_dependency_line(args, dict(), False, lines[3])
- expected = gen.CargoTreeDependency(cargo.CrateKey(
- "unicode-xid", "0.2.2"),
- full_version="0.2.2",
- features=["default"])
- self.assertEqual(r, expected)
- # │ ├── quote v1.0.10 (/path/to/chromium/src/third_party/rust/quote/v1/crate) default,proc-macro
- r = gen._parse_cargo_tree_dependency_line(args, dict(), False, lines[4])
- expected = gen.CargoTreeDependency(
- cargo.CrateKey("quote", "1.0.10"),
- full_version="1.0.10",
- crate_path="/path/to/chromium/src/third_party/rust/quote/v1/crate",
- features=["default", "proc-macro"])
- self.assertEqual(r, expected)
- # │ │ └── proc-macro2 v1.0.32 default,proc-macro,span-locations (*)
- r = gen._parse_cargo_tree_dependency_line(args, dict(), False, lines[5])
- expected = gen.CargoTreeDependency(
- cargo.CrateKey("proc-macro2", "1.0.32"),
- full_version="1.0.32",
- features=["default", "proc-macro", "span-locations"])
- self.assertEqual(r, expected)
- # │ └── syn v1.0.81 clone-impls,default,derive,full,parsing,printing,proc-macro,quote
- r = gen._parse_cargo_tree_dependency_line(args, dict(), False, lines[6])
- expected = gen.CargoTreeDependency(cargo.CrateKey("syn", "1.0.81"),
- full_version="1.0.81",
- features=[
- "clone-impls", "default",
- "derive", "full", "parsing",
- "printing", "proc-macro", "quote"
- ])
- self.assertEqual(r, expected)
- # │ ├── proc-macro2 v1.0.32 default,proc-macro,span-locations (*)
- r = gen._parse_cargo_tree_dependency_line(args, dict(), False, lines[7])
- expected = gen.CargoTreeDependency(
- cargo.CrateKey("proc-macro2", "1.0.32"),
- full_version="1.0.32",
- features=["default", "proc-macro", "span-locations"])
- self.assertEqual(r, expected)
- # │ ├── quote v1.0.10 default,proc-macro (*)
- r = gen._parse_cargo_tree_dependency_line(args, dict(), False, lines[8])
- expected = gen.CargoTreeDependency(cargo.CrateKey("quote", "1.0.10"),
- full_version="1.0.10",
- features=["default", "proc-macro"])
- self.assertEqual(r, expected)
- # │ └── unicode-xid v0.2.2
- r = gen._parse_cargo_tree_dependency_line(args, dict(), False, lines[9])
- expected = gen.CargoTreeDependency(cargo.CrateKey(
- "unicode-xid", "0.2.2"),
- full_version="0.2.2")
- self.assertEqual(r, expected)
- # └── link-cplusplus v1.0.5 default
- r = gen._parse_cargo_tree_dependency_line(args, dict(), False,
- lines[10])
- d = gen.CargoTreeDependency(cargo.CrateKey("link-cplusplus", "1.0.5"),
- full_version="1.0.5",
- features=["default"])
- self.assertEqual(r, d)
- def test_third_party_toml(self):
- args = self.make_args()
- THIRD_PARTY_TOML = """
- # This dependency has no extensions
- [dependencies]
- cxxbridge-macro = "1"
- # This dependency has an extension, and is default-visible to first-party code.
- [dependencies.link-cplusplus]
- build-script-outputs = [ "src/link.rs", "src/cplusplus.rs" ]
- # This dependency is not visible to first-party code thanks to the extension.
- [dependencies.syn]
- allow-first-party-usage = false
- """
- # Here we are simulating parsing our special third_party.toml file, so
- # we need to present the contents of that file to the
- # _parse_cargo_tree_dependency_line() function, in order for it to look
- # for extensions.
- toml_content = toml.loads(THIRD_PARTY_TOML)
- line = "├── cxxbridge-macro v1.0.56 (proc-macro)"
- r = gen._parse_cargo_tree_dependency_line(args, toml_content, True,
- line)
- d = gen.CargoTreeDependency(
- cargo.CrateKey("cxxbridge-macro", "1.0.56"),
- full_version="1.0.56",
- # Deps from third_party.toml are visible to first-party code by
- # default.
- is_for_first_party_code=True)
- self.assertEqual(r, d)
- line = "├── link-cplusplus v1.0.5 default"
- r = gen._parse_cargo_tree_dependency_line(args, toml_content, True,
- line)
- d = gen.CargoTreeDependency(
- cargo.CrateKey("link-cplusplus", "1.0.5"),
- full_version="1.0.5",
- features=["default"],
- is_for_first_party_code=True,
- # link-cplusplus has build script outputs listed in our
- # third_party.toml.
- build_script_outputs={"src/link.rs", "src/cplusplus.rs"})
- self.assertEqual(r, d)
- line = "└── syn v1.0.81 clone-impls,default"
- r = gen._parse_cargo_tree_dependency_line(args, toml_content, True,
- line)
- d = gen.CargoTreeDependency(
- cargo.CrateKey("syn", "1.0.81"),
- full_version="1.0.81",
- features=["clone-impls", "default"],
- # Deps from third_party.toml are visible to first-party code unless
- # they opt out explicitly, which our syn dependency has done.
- is_for_first_party_code=False)
- self.assertEqual(r, d)
- def test_third_party_toml_dev_deps(self):
- args = self.make_args()
- THIRD_PARTY_TOML = """
- [dependencies]
- # Nothing. We're testing dev-dependencies here.
- [dev-dependencies]
- cxxbridge-macro = "1"
- # This dependency has an extension, and is default-visible to first-party code.
- [dev-dependencies.link-cplusplus]
- build-script-outputs = [ "src/link.rs", "src/cplusplus.rs" ]
- # This dependency is not visible to first-party code thanks to the extension.
- [dev-dependencies.syn]
- allow-first-party-usage = false
- """
- # Here we are simulating parsing our special third_party.toml file, so
- # we need to present the contents of that file to the
- # _parse_cargo_tree_dependency_line() function, in order for it to look
- # for extensions.
- toml_content = toml.loads(THIRD_PARTY_TOML)
- line = "├── cxxbridge-macro v1.0.56 (proc-macro)"
- r = gen._parse_cargo_tree_dependency_line(args, toml_content, True,
- line)
- d = gen.CargoTreeDependency(
- cargo.CrateKey("cxxbridge-macro", "1.0.56"),
- full_version="1.0.56",
- # Deps from third_party.toml are visible to first-party code by
- # default.
- is_for_first_party_code=True)
- self.assertEqual(r, d)
- line = "├── link-cplusplus v1.0.5 default"
- r = gen._parse_cargo_tree_dependency_line(args, toml_content, True,
- line)
- d = gen.CargoTreeDependency(
- cargo.CrateKey("link-cplusplus", "1.0.5"),
- full_version="1.0.5",
- features=["default"],
- is_for_first_party_code=True,
- # link-cplusplus has build script outputs listed in our
- # third_party.toml.
- build_script_outputs={"src/link.rs", "src/cplusplus.rs"})
- self.assertEqual(r, d)
- line = "└── syn v1.0.81 clone-impls,default"
- r = gen._parse_cargo_tree_dependency_line(args, toml_content, True,
- line)
- d = gen.CargoTreeDependency(
- cargo.CrateKey("syn", "1.0.81"),
- full_version="1.0.81",
- features=["clone-impls", "default"],
- # Deps from third_party.toml are visible to first-party code unless
- # they opt out explicitly, which our syn dependency has done.
- is_for_first_party_code=False)
- self.assertEqual(r, d)
- def test_get_archs_third_party_toml(self):
- crate_key = None # For third_party.toml there's none.
- usage_data = None # For third_party.toml there's none.
- # Test what happens when there is a `target` on a dependency.
- toml_content = toml.loads("""
- [dependencies]
- all-platform-crate = "1"
- [target."cfg(windows)".dependencies]
- windows-only-crate = "2"
- """)
- # Test case without a target specified on the command line. Since
- # there's differences per-architecture in the TOML, we will have to test
- # all architectures.
- arch_specific = gen._get_archs_of_interest(toml_content, usage_data,
- None)
- # Not true as there's a arch-specific dependency.
- self.assertFalse(arch_specific.is_single_arch())
- self.assertSetEqual(self.all_archs(), arch_specific.archs_to_test())
- # Test case with a target specified on the command line that matches
- # the target. We only need to test the target the user specified.
- arch_specific = gen._get_archs_of_interest(toml_content, usage_data,
- "x86_64-pc-windows-msvc")
- # We only ever care about one arch, so everything is single-arch.
- self.assertTrue(arch_specific.is_single_arch())
- self.assertSetEqual({"x86_64-pc-windows-msvc"},
- arch_specific.archs_to_test())
- # Test case with a target specified on the command line that does not
- # match the target. We only need to test the target the user specified,
- # and we're not smart enough to prune it yet..
- arch_specific = gen._get_archs_of_interest(toml_content, usage_data,
- "x86_64-unknown-linux-gnu")
- # We only ever care about one arch, so everything is single-arch.
- self.assertTrue(arch_specific.is_single_arch())
- self.assertSetEqual({"x86_64-unknown-linux-gnu"},
- arch_specific.archs_to_test())
- # Test what happens when there is no `target` on a dependency.
- toml_content = toml.loads("""
- [dependencies]
- all-platform-crate = "1"
- """)
- # Test case without a target specified on the command line.
- arch_specific = gen._get_archs_of_interest(toml_content, usage_data,
- None)
- # Is true since we can apply a single architecture's result to other
- # ones.
- self.assertTrue(arch_specific.is_single_arch())
- # We only need to test one architecture and copy its results to the
- # rest.
- self.assertEqual(len(arch_specific.archs_to_test()), 1)
- # We don't care which architecture will be tested, but in the next test
- # case we do, so make sure the arbitrary architecture here isn't doesn't
- # unluckily collide with our next test.
- self.assertFalse({"x86_64-pc-windows-msvc"
- }.issubset(arch_specific.archs_to_test()))
- # Test case with a target specified on the command line.
- arch_specific = gen._get_archs_of_interest(toml_content, usage_data,
- "x86_64-pc-windows-msvc")
- self.assertTrue(arch_specific.is_single_arch())
- # We should test the architecture specified.
- self.assertSetEqual({"x86_64-pc-windows-msvc"},
- arch_specific.archs_to_test())
- # Ensure we are OK with a [target] section with no dependencies
- toml_content = toml.loads("""
- [dependencies]
- all-platform-crate = "1"
- [target."cfg(windows)"]
- """)
- arch_specific = gen._get_archs_of_interest(toml_content, usage_data,
- None)
- self.assertTrue(arch_specific.is_single_arch())
- def make_fake_parent(self, child_name: str,
- archset_where_parent_used: compiler.ArchSet,
- parent_is_arch_specific: bool,
- parent_has_arch_specific_deps: bool
- ) -> gen.ArchSpecific:
- if not parent_has_arch_specific_deps:
- toml_content = toml.loads("""
- [dependencies]
- {} = "1"
- """.format(child_name))
- else:
- toml_content = toml.loads("""
- [target."cfg(windows)".dependencies]
- {} = "1"
- """.format(child_name))
- parent_crate_data = gen.PerCrateData()
- parent_crate_data.arch_specific = parent_is_arch_specific
- parent_crate_data.used_on_archs = archset_where_parent_used
- return gen._get_archs_of_interest(toml_content, parent_crate_data, None)
- def make_fake_dep(self, dep_key: cargo.CrateKey,
- parent_requested_features_of_dep: list[str],
- dep_for_first_party_code: bool,
- dep_build_script_outputs: set[str]):
- return gen.CargoTreeDependency(
- dep_key,
- features=parent_requested_features_of_dep,
- is_for_first_party_code=dep_for_first_party_code,
- build_script_outputs=dep_build_script_outputs)
- def add_fake_dependency_edges(self, build_data: gen.BuildData,
- new_keys: set[cargo.CrateKey], **kwargs):
- parent_name: str = kwargs["parent_name"]
- parent_arch_specific = self.make_fake_parent(
- kwargs["dep_name"], kwargs["archset_where_parent_used"],
- kwargs["parent_is_arch_specific"],
- kwargs["parent_has_arch_specific_deps"])
- dep_key = cargo.CrateKey(kwargs["dep_name"], "1.2.3")
- dep = self.make_fake_dep(dep_key,
- kwargs["parent_requested_features_of_dep"],
- kwargs["dep_for_first_party_code"],
- kwargs["dep_build_script_outputs"])
- parent_crate_key = cargo.CrateKey(parent_name,
- "1.2.3") if parent_name else None
- gen._add_edges_for_dep_on_target_arch(build_data, parent_crate_key,
- parent_arch_specific,
- kwargs["parent_usage"],
- kwargs["parent_output"], dep,
- kwargs["computing_arch"],
- new_keys)
- return dep_key
- def test_add_edges(self):
- build_data = gen.BuildData()
- new_keys = set()
- for_first_party_code = True
- build_script_outputs = {"src/child-outs.rs"}
- dep_key = self.add_fake_dependency_edges(
- build_data,
- new_keys,
- parent_name=None, # No parent crate from third_party.toml.
- # Parent used everywhere.
- archset_where_parent_used=compiler.ArchSet.ALL(),
- parent_is_arch_specific=False,
- parent_has_arch_specific_deps=False,
- # computing_arch is chosen arbitrarily since the result will apply
- # to all as parent_has_arch_specific_deps is False
- computing_arch="aarch64-apple-darwin",
- # Parent used for a binary.
- parent_usage=cargo.CrateUsage.FOR_NORMAL,
- # Adding a build-dependency.
- parent_output=cargo.CrateBuildOutput.BUILDRS,
- dep_name="child-name",
- parent_requested_features_of_dep=["feature1", "feature2"],
- dep_for_first_party_code=for_first_party_code,
- dep_build_script_outputs=build_script_outputs)
- # The new crate was added to new_keys
- self.assertSetEqual(new_keys, {dep_key})
- # The child crate should be in the BuildData
- self.assertSetEqual(build_data.for_buildrs.all_crates(), {dep_key})
- self.assertSetEqual(build_data.for_normal.all_crates(), {dep_key})
- self.assertSetEqual(build_data.for_tests.all_crates(), {dep_key})
- # In buildrs usage, (since the parent was building BUILDRS output),
- # the dependency will be used and have data populated.
- with build_data.for_buildrs.per_crate(dep_key) as crate:
- # The requested features will be used on _all_ architectures, even
- # since the ArchSpecific tests one but applies to all.
- features = crate.features.all_archsets()
- self.assertListSortedEqual(features, [
- ("feature1", compiler.ArchSet.ALL()),
- ("feature2", compiler.ArchSet.ALL()),
- ])
- # Similarly, the crate is used everywhere. This should always be a
- # superset of the architectures where features are enabled.
- self.assertEqual(crate.used_on_archs, compiler.ArchSet.ALL())
- # Since the ArchSpecific said the parent is not arch-specific, and
- # there's no arch-specific deps, the dependency will not be arch-
- # specific.
- self.assertFalse(crate.arch_specific)
- self.assertEqual(crate.for_first_party, for_first_party_code)
- self.assertEqual(crate.build_script_outputs, build_script_outputs)
- # There's no edges from the new dependency since we haven't added
- # those.
- for o in cargo.CrateBuildOutput:
- self.assertSetEqual(crate.deps[o].all_deps(),
- set(),
- msg="For output type {}".format(o))
- # Other usages are not used, and have no features enabled, since the
- # parent crate is only using this dependency for tests so far, as those
- # are the only edges we added.
- with build_data.for_normal.per_crate(dep_key) as crate:
- self.assertListSortedEqual(crate.features.all_archsets(), [])
- self.assertEqual(crate.used_on_archs, compiler.ArchSet.EMPTY())
- self.assertFalse(crate.arch_specific)
- self.assertEqual(crate.for_first_party, for_first_party_code)
- self.assertEqual(crate.build_script_outputs, build_script_outputs)
- with build_data.for_tests.per_crate(dep_key) as crate:
- self.assertListSortedEqual(crate.features.all_archsets(), [])
- self.assertEqual(crate.used_on_archs, compiler.ArchSet.EMPTY())
- self.assertFalse(crate.arch_specific)
- self.assertEqual(crate.for_first_party, for_first_party_code)
- self.assertEqual(crate.build_script_outputs, build_script_outputs)
- # The parent would have edges to the child but this was a dep from the
- # third_party.toml, so there's no parent.
- # Now add a transitive dependency, which will have a parent: the child
- # that we added above. We will only add edges to the grand child on
- # Windows.
- parent_key = dep_key
- for_first_party_code = False
- build_script_outputs = {"src/grand-child-outs.rs"}
- dep_key = self.add_fake_dependency_edges(
- build_data,
- new_keys,
- parent_name="child-name", # The parent crate of the grand-child.
- # Parent used everywhere.
- archset_where_parent_used=compiler.ArchSet.ALL(),
- parent_is_arch_specific=False,
- parent_has_arch_specific_deps=True,
- # Act as if cargo-tree sees the grand-child on Windows, so we're
- # adding an edge there. Since parent_has_arch_specific_deps is True,
- # the edge won't be added to other architectures automatically.
- computing_arch="x86_64-pc-windows-msvc",
- # Parent was used for buildrs.
- parent_usage=cargo.CrateUsage.FOR_BUILDRS,
- # Adding a build-dependency.
- parent_output=cargo.CrateBuildOutput.BUILDRS,
- dep_name="grand-child-name",
- parent_requested_features_of_dep=["featureA", "featureB"],
- dep_for_first_party_code=False,
- dep_build_script_outputs=build_script_outputs)
- current_archset = compiler.ArchSet(initial={"x86_64-pc-windows-msvc"})
- # The new crate was added to new_keys
- self.assertSetEqual(new_keys, {parent_key, dep_key})
- # The grand-child crate should be in the BuildData
- self.assertSetEqual(build_data.for_buildrs.all_crates(),
- {parent_key, dep_key})
- self.assertSetEqual(build_data.for_normal.all_crates(),
- {parent_key, dep_key})
- self.assertSetEqual(build_data.for_tests.all_crates(),
- {parent_key, dep_key})
- # In buildrs usage, (since its parent was building BUILDRS output),
- # the dependency will be used and have data populated.
- with build_data.for_buildrs.per_crate(dep_key) as crate:
- # The requested features will be used on the architecture we're
- # processing, since they can't be generalized to all architectures.
- features = crate.features.all_archsets()
- self.assertListSortedEqual(features,
- [("featureA", current_archset),
- ("featureB", current_archset)])
- # Similarly, the crate is used on the architecture we're processing.
- self.assertEqual(crate.used_on_archs, current_archset)
- # Since the dep is in a target rule (parent_has_arch_specific_deps),
- # the crate is considered arch-specific.
- self.assertTrue(crate.arch_specific)
- self.assertEqual(crate.for_first_party, for_first_party_code)
- self.assertEqual(crate.build_script_outputs, build_script_outputs)
- # There's no edges from the new dependency since we haven't added
- # those.
- for o in cargo.CrateBuildOutput:
- self.assertSetEqual(crate.deps[o].all_deps(),
- set(),
- msg="For output type {}".format(o))
- # Other usages are not used, and have no features enabled, since the
- # parent crate is only using this dependency for tests so far, as those
- # are the only edges we added.
- with build_data.for_normal.per_crate(dep_key) as crate:
- self.assertListSortedEqual(crate.features.all_archsets(), [])
- self.assertEqual(crate.used_on_archs, compiler.ArchSet.EMPTY())
- self.assertFalse(crate.arch_specific)
- self.assertEqual(crate.for_first_party, for_first_party_code)
- self.assertEqual(crate.build_script_outputs, build_script_outputs)
- with build_data.for_tests.per_crate(dep_key) as crate:
- self.assertListSortedEqual(crate.features.all_archsets(), [])
- self.assertEqual(crate.used_on_archs, compiler.ArchSet.EMPTY())
- self.assertFalse(crate.arch_specific)
- self.assertEqual(crate.for_first_party, for_first_party_code)
- self.assertEqual(crate.build_script_outputs, build_script_outputs)
- # The child crate now depends on the grand-child crate on the computed.
- # architecture, only for it's buildrs script.
- with build_data.for_buildrs.per_crate(parent_key) as crate:
- self.assertSetEqual(
- crate.deps[cargo.CrateBuildOutput.BUILDRS].all_deps(),
- {dep_key})
- self.assertSetEqual(
- crate.deps[cargo.CrateBuildOutput.NORMAL].all_deps(), set())
- self.assertSetEqual(
- crate.deps[cargo.CrateBuildOutput.TESTS].all_deps(), set())
- # We haven't considered the parent crate being built into a crate's
- # lib/bin as a normal dependency, or tests as a dev-dependency so
- # there's no edges.
- with build_data.for_normal.per_crate(parent_key) as crate:
- for o in cargo.CrateBuildOutput:
- self.assertSetEqual(crate.deps[o].all_deps(),
- set(),
- msg="For output type {}".format(o))
- with build_data.for_tests.per_crate(parent_key) as crate:
- for o in cargo.CrateBuildOutput:
- self.assertSetEqual(crate.deps[o].all_deps(),
- set(),
- msg="For output type {}".format(o))
- new_keys = set()
- # Now we again compute edges between the child and grand-child, for
- # another architecture, and for the child's normal build output. It
- # can use different features of the grand-child there.
- dep_key = self.add_fake_dependency_edges(
- build_data,
- new_keys,
- parent_name="child-name", # The parent crate of the grand-child.
- # Parent used everywhere.
- archset_where_parent_used=compiler.ArchSet.ALL(),
- parent_is_arch_specific=False,
- parent_has_arch_specific_deps=True,
- # Act as if cargo-tree sees the grand-child on Fuchsia, so we're
- # adding an edge there. Since parent_has_arch_specific_deps is True,
- # the edge won't be added to other architectures automatically.
- computing_arch="x86_64-fuchsia",
- # Parent was used for a lib/bin.
- parent_usage=cargo.CrateUsage.FOR_NORMAL,
- # Adding a build-dependency.
- parent_output=cargo.CrateBuildOutput.BUILDRS,
- dep_name="grand-child-name",
- parent_requested_features_of_dep=["featureB", "featureC"],
- dep_for_first_party_code=False,
- dep_build_script_outputs=build_script_outputs)
- current_archset = compiler.ArchSet(initial={"x86_64-fuchsia"})
- before_archset = compiler.ArchSet(initial={"x86_64-pc-windows-msvc"})
- union_archset = compiler.ArchSet(
- initial={"x86_64-pc-windows-msvc", "x86_64-fuchsia"})
- # The grand-child is being used on a new platform, and is arch-specific,
- # so it will need to compute its deps again.
- self.assertSetEqual(new_keys, {dep_key})
- # In buildrs usage, (since its parent was building BUILDRS output),
- # the dependency will be used and have data populated.
- with build_data.for_buildrs.per_crate(dep_key) as crate:
- # The requested features will be used on the architecture we're
- # processing, since they can't be generalized to all architectures.
- features = crate.features.all_archsets()
- self.assertListSortedEqual(features, [
- ("featureA", before_archset),
- ("featureB", union_archset),
- ("featureC", current_archset),
- ])
- # The crate is used on the union architectures.
- self.assertEqual(crate.used_on_archs, union_archset)
- # There's no edges from the new dependency since we haven't added
- # those.
- for o in cargo.CrateBuildOutput:
- self.assertSetEqual(crate.deps[o].all_deps(),
- set(),
- msg="For output type {}".format(o))
- # Other usages are not used, and have no features enabled, since the
- # parent crate is only using this dependency for tests so far, as those
- # are the only edges we added.
- with build_data.for_normal.per_crate(dep_key) as crate:
- self.assertListSortedEqual(crate.features.all_archsets(), [])
- self.assertEqual(crate.used_on_archs, compiler.ArchSet.EMPTY())
- self.assertFalse(crate.arch_specific)
- self.assertEqual(crate.for_first_party, for_first_party_code)
- self.assertEqual(crate.build_script_outputs, build_script_outputs)
- with build_data.for_tests.per_crate(dep_key) as crate:
- self.assertListSortedEqual(crate.features.all_archsets(), [])
- self.assertEqual(crate.used_on_archs, compiler.ArchSet.EMPTY())
- self.assertFalse(crate.arch_specific)
- self.assertEqual(crate.for_first_party, for_first_party_code)
- self.assertEqual(crate.build_script_outputs, build_script_outputs)
- # The child crate still depends on the grand-child crate for its buildrs
- # script when building built as a build-dependency.
- with build_data.for_buildrs.per_crate(parent_key) as crate:
- self.assertSetEqual(
- crate.deps[cargo.CrateBuildOutput.BUILDRS].all_deps(),
- {dep_key})
- self.assertSetEqual(
- crate.deps[cargo.CrateBuildOutput.NORMAL].all_deps(), set())
- self.assertSetEqual(
- crate.deps[cargo.CrateBuildOutput.TESTS].all_deps(), set())
- # The child crate now _also_ depends on the grand-child crate for its
- # buildrs script when building built as a normal dependency.
- with build_data.for_normal.per_crate(parent_key) as crate:
- self.assertSetEqual(
- crate.deps[cargo.CrateBuildOutput.BUILDRS].all_deps(),
- {dep_key})
- self.assertSetEqual(
- crate.deps[cargo.CrateBuildOutput.NORMAL].all_deps(), set())
- self.assertSetEqual(
- crate.deps[cargo.CrateBuildOutput.TESTS].all_deps(), set())
- # We haven't considered the parent crate being built into a crate's
- # tests as a dev-dependency so there's no edges.
- with build_data.for_tests.per_crate(parent_key) as crate:
- for o in cargo.CrateBuildOutput:
- self.assertSetEqual(crate.deps[o].all_deps(),
- set(),
- msg="For output type {}".format(o))
- def test_copyright_year(self):
- modern = b"# Copyright 2001 The Chromium Authors. All rights reserved."
- with tempfile.NamedTemporaryFile() as f:
- f.write(modern)
- f.flush()
- self.assertEqual(gen._get_copyright_year(f.name), "2001")
- ancient = b"# Copyright (c) 2001 The Chromium Authors. All rights reserved."
- with tempfile.NamedTemporaryFile() as f:
- f.write(ancient)
- f.flush()
- self.assertEqual(gen._get_copyright_year(f.name), "2001")
- self.assertEqual(gen._get_copyright_year("/file/does/not/exist"),
- str(datetime.now().year))
|