[testonly] Allow configs to be testonly
Bug: 214
Change-Id: Idec794f14f5755eebc1e3ed879c19b015f6d433b
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/12680
Reviewed-by: David Turner <digit@google.com>
Reviewed-by: Brett Wilson <brettw@chromium.org>
Commit-Queue: Shai Barack <shayba@google.com>
diff --git a/src/gn/config_values_generator.h b/src/gn/config_values_generator.h
index fd508d4..d006140 100644
--- a/src/gn/config_values_generator.h
+++ b/src/gn/config_values_generator.h
@@ -41,6 +41,6 @@
" Flags: cflags, cflags_c, cflags_cc, cflags_objc, cflags_objcc,\n" \
" asmflags, defines, include_dirs, inputs, ldflags, lib_dirs,\n" \
" libs, precompiled_header, precompiled_source, rustflags,\n" \
- " rustenv, swiftflags\n"
+ " rustenv, swiftflags, testonly\n"
#endif // TOOLS_GN_CONFIG_VALUES_GENERATOR_H_
diff --git a/src/gn/item.h b/src/gn/item.h
index 2942a66..dd1a606 100644
--- a/src/gn/item.h
+++ b/src/gn/item.h
@@ -38,6 +38,9 @@
const ParseNode* defined_from() const { return defined_from_; }
void set_defined_from(const ParseNode* df) { defined_from_ = df; }
+ bool testonly() const { return testonly_; }
+ void set_testonly(bool value) { testonly_ = value; }
+
Visibility& visibility() { return visibility_; }
const Visibility& visibility() const { return visibility_; }
@@ -69,11 +72,14 @@
virtual bool OnResolved(Err* err);
private:
+ bool CheckTestonly(Err* err) const;
+
const Settings* settings_;
Label label_;
SourceFileSet build_dependency_files_;
const ParseNode* defined_from_;
+ bool testonly_ = false;
Visibility visibility_;
};
diff --git a/src/gn/target.cc b/src/gn/target.cc
index da6b7e4..ded575a 100644
--- a/src/gn/target.cc
+++ b/src/gn/target.cc
@@ -43,7 +43,7 @@
}
}
-Err MakeTestOnlyError(const Target* from, const Target* to) {
+Err MakeTestOnlyError(const Item* from, const Item* to) {
return Err(
from->defined_from(), "Test-only dependency not allowed.",
from->label().GetUserVisibleName(false) +
@@ -1142,6 +1142,16 @@
}
}
+ // Verify no configs have "testonly" set.
+ for (ConfigValuesIterator iter(this); !iter.done(); iter.Next()) {
+ if (const Config* config = iter.GetCurrentConfig()) {
+ if (config->testonly()) {
+ *err = MakeTestOnlyError(this, config);
+ return false;
+ }
+ }
+ }
+
return true;
}
diff --git a/src/gn/target.h b/src/gn/target.h
index 59fe806..d88f0a5 100644
--- a/src/gn/target.h
+++ b/src/gn/target.h
@@ -214,9 +214,6 @@
}
std::vector<std::string>& walk_keys() { return generated_file().walk_keys_; }
- bool testonly() const { return testonly_; }
- void set_testonly(bool value) { testonly_ = value; }
-
OutputFile write_runtime_deps_output() const {
return write_runtime_deps_output_;
}
@@ -474,7 +471,6 @@
FileList public_headers_;
bool check_includes_ = true;
bool complete_static_lib_ = false;
- bool testonly_ = false;
std::vector<std::string> data_;
std::unique_ptr<BundleData> bundle_data_;
OutputFile write_runtime_deps_output_;
diff --git a/src/gn/target_unittest.cc b/src/gn/target_unittest.cc
index f8cbcd1..b4ea699 100644
--- a/src/gn/target_unittest.cc
+++ b/src/gn/target_unittest.cc
@@ -628,6 +628,31 @@
ASSERT_FALSE(product.OnResolved(&err));
}
+// Configs can be testonly too.
+// Repeat the testonly test with a config.
+TEST_F(TargetTest, TestonlyConfig) {
+ TestWithScope setup;
+ Err err;
+
+ // "testconfig" is a test-only config.
+ Config testconfig(setup.settings(), Label(SourceDir("//test/"), "config"));
+ testconfig.set_testonly(true);
+ testconfig.visibility().SetPublic();
+ ASSERT_TRUE(testconfig.OnResolved(&err));
+
+ // "test" is a test-only executable that uses testconfig, this is OK.
+ TestTarget test(setup, "//test:test", Target::EXECUTABLE);
+ test.set_testonly(true);
+ test.configs().push_back(LabelConfigPair(&testconfig));
+ ASSERT_TRUE(test.OnResolved(&err));
+
+ // "product" is a non-test that uses testconfig. This should fail.
+ TestTarget product(setup, "//app:product", Target::EXECUTABLE);
+ product.set_testonly(false);
+ product.configs().push_back(LabelConfigPair(&testconfig));
+ ASSERT_FALSE(product.OnResolved(&err));
+}
+
TEST_F(TargetTest, PublicConfigs) {
TestWithScope setup;
Err err;