Commit 043a15dd authored by liaoyuke's avatar liaoyuke Committed by Commit bot

Add functionality to find xctest files under application target.

Previously, our generated Xcode project has the issue that Xcode couldn't find
our xctests. And to fix it, one must first find the list of xctest files
under each of the application targets and then associate them with the
corresponding xctest target.

This CL enables identifying application targets and also find the list of xctest
files (xctests.mm and egtest.mm) under them recursively.

BUG=614818

Review-Url: https://codereview.chromium.org/2574643002
Cr-Commit-Position: refs/heads/master@{#441482}
parent f344fae1
......@@ -31,6 +31,12 @@
namespace {
using TargetToFileList = std::unordered_map<const Target*, Target::FileList>;
const char kEarlGreyFileNameIdentifier[] = "egtest.mm";
const char kXCTestFileNameIdentifier[] = "xctest.mm";
const char kXCTestModuleTargetNamePostfix[] = "_module";
struct SafeEnvironmentVariableInfo {
const char* name;
bool capture_at_generation;
......@@ -86,6 +92,107 @@ std::string GetBuildScript(const std::string& target_name,
return script.str();
}
bool IsApplicationTarget(const Target* target) {
return target->output_type() == Target::CREATE_BUNDLE &&
target->bundle_data().product_type() ==
"com.apple.product-type.application";
}
bool IsXCTestModuleTarget(const Target* target) {
return target->output_type() == Target::CREATE_BUNDLE &&
target->bundle_data().product_type() ==
"com.apple.product-type.bundle.unit-test" &&
base::EndsWith(target->label().name(), kXCTestModuleTargetNamePostfix,
base::CompareCase::SENSITIVE);
}
const Target* FindXCTestApplicationTarget(
const Target* xctest_module_target,
const std::vector<const Target*>& targets) {
DCHECK(IsXCTestModuleTarget(xctest_module_target));
DCHECK(base::EndsWith(xctest_module_target->label().name(),
kXCTestModuleTargetNamePostfix,
base::CompareCase::SENSITIVE));
std::string application_target_name =
xctest_module_target->label().name().substr(
0, xctest_module_target->label().name().size() -
strlen(kXCTestModuleTargetNamePostfix));
for (const Target* target : targets) {
if (target->label().name() == application_target_name) {
return target;
}
}
NOTREACHED();
return nullptr;
}
// Returns the corresponding application targets given XCTest module targets.
void FindXCTestApplicationTargets(
const std::vector<const Target*>& xctest_module_targets,
const std::vector<const Target*>& targets,
std::vector<const Target*>* xctest_application_targets) {
for (const Target* xctest_module_target : xctest_module_targets) {
xctest_application_targets->push_back(
FindXCTestApplicationTarget(xctest_module_target, targets));
}
}
// Searches the list of xctest files recursively under |target|.
void SearchXCTestFiles(const Target* target,
TargetToFileList* xctest_files_per_target) {
// Early return if already visited and processed.
if (xctest_files_per_target->find(target) != xctest_files_per_target->end())
return;
Target::FileList xctest_files;
for (const SourceFile& file : target->sources()) {
if (base::EndsWith(file.GetName(), kEarlGreyFileNameIdentifier,
base::CompareCase::SENSITIVE) ||
base::EndsWith(file.GetName(), kXCTestFileNameIdentifier,
base::CompareCase::SENSITIVE)) {
xctest_files.push_back(file);
}
}
// Call recursively on public and private deps.
for (const auto& target : target->public_deps()) {
SearchXCTestFiles(target.ptr, xctest_files_per_target);
const Target::FileList& deps_xctest_files =
(*xctest_files_per_target)[target.ptr];
xctest_files.insert(xctest_files.end(), deps_xctest_files.begin(),
deps_xctest_files.end());
}
for (const auto& target : target->private_deps()) {
SearchXCTestFiles(target.ptr, xctest_files_per_target);
const Target::FileList& deps_xctest_files =
(*xctest_files_per_target)[target.ptr];
xctest_files.insert(xctest_files.end(), deps_xctest_files.begin(),
deps_xctest_files.end());
}
// Sort xctest_files to remove duplicates.
std::sort(xctest_files.begin(), xctest_files.end());
xctest_files.erase(std::unique(xctest_files.begin(), xctest_files.end()),
xctest_files.end());
xctest_files_per_target->insert(std::make_pair(target, xctest_files));
}
// Finds the list of xctest files recursively under each of the application
// targets.
void FindXCTestFilesForTargets(
const std::vector<const Target*>& application_targets,
std::vector<Target::FileList>* file_lists) {
TargetToFileList xctest_files_per_target;
for (const Target* target : application_targets) {
DCHECK(IsApplicationTarget(target));
SearchXCTestFiles(target, &xctest_files_per_target);
file_lists->push_back(xctest_files_per_target[target]);
}
}
class CollectPBXObjectsPerClassHelper : public PBXObjectVisitor {
public:
CollectPBXObjectsPerClassHelper() {}
......@@ -266,6 +373,18 @@ bool XcodeWriter::FilterTargets(const BuildSettings* build_settings,
return true;
}
// static
void XcodeWriter::FilterXCTestModuleTargets(
const std::vector<const Target*>& targets,
std::vector<const Target*>* xctest_module_targets) {
for (const Target* target : targets) {
if (!IsXCTestModuleTarget(target))
continue;
xctest_module_targets->push_back(target);
}
}
void XcodeWriter::CreateProductsProject(
const std::vector<const Target*>& targets,
const PBXAttributes& attributes,
......@@ -278,6 +397,20 @@ void XcodeWriter::CreateProductsProject(
std::unique_ptr<PBXProject> main_project(
new PBXProject("products", config_name, source_path, attributes));
// Filter xctest module and application targets and find list of xctest files
// recursively under them.
std::vector<const Target*> xctest_module_targets;
FilterXCTestModuleTargets(targets, &xctest_module_targets);
std::vector<const Target*> xctest_application_targets;
FindXCTestApplicationTargets(xctest_module_targets, targets,
&xctest_application_targets);
DCHECK_EQ(xctest_module_targets.size(), xctest_application_targets.size());
std::vector<Target::FileList> xctest_file_lists;
FindXCTestFilesForTargets(xctest_application_targets, &xctest_file_lists);
DCHECK_EQ(xctest_application_targets.size(), xctest_file_lists.size());
std::string build_path;
std::unique_ptr<base::Environment> env(base::Environment::Create());
......
......@@ -60,6 +60,11 @@ class XcodeWriter {
std::vector<const Target*>* targets,
Err* err);
// Filters list of targets to only return ones that are xctest module bundles.
static void FilterXCTestModuleTargets(
const std::vector<const Target*>& targets,
std::vector<const Target*>* xctest_module_targets);
// Generate the "products.xcodeproj" project that reference all products
// (i.e. targets that have a build artefact usable from Xcode, mostly
// application bundles).
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment