Loading tools/bit/main.cpp +133 −3 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ using namespace std; #define NATIVE_TESTS "NATIVE_TESTS" /** * An entry from the command line for something that will be built, installed, * and/or tested. Loading Loading @@ -132,6 +134,32 @@ InstallApk::InstallApk(const string& filename, bool always) { } struct PushedFile { TrackedFile file; string dest; PushedFile(); PushedFile(const PushedFile& that); PushedFile(const string& filename, const string& dest); ~PushedFile() {}; }; PushedFile::PushedFile() { } PushedFile::PushedFile(const PushedFile& that) :file(that.file), dest(that.dest) { } PushedFile::PushedFile(const string& f, const string& d) :file(f), dest(d) { } /** * Record for an test that is going to be launched. Loading Loading @@ -658,12 +686,14 @@ run_phases(vector<Target*> targets, const Options& options) } // Figure out whether we need to sync the system and which apks to install string systemPath = buildOut + "/target/product/" + buildDevice + "/system/"; string dataPath = buildOut + "/target/product/" + buildDevice + "/data/"; string deviceTargetPath = buildOut + "/target/product/" + buildDevice; string systemPath = deviceTargetPath + "/system/"; string dataPath = deviceTargetPath + "/data/"; bool syncSystem = false; bool alwaysSyncSystem = false; vector<string> systemFiles; vector<InstallApk> installApks; vector<PushedFile> pushedFiles; for (size_t i=0; i<targets.size(); i++) { Target* target = targets[i]; if (target->install) { Loading @@ -687,6 +717,11 @@ run_phases(vector<Target*> targets, const Options& options) installApks.push_back(InstallApk(file, !target->build)); continue; } // If it's a native test module, push it. if (target->module.HasClass(NATIVE_TESTS) && starts_with(file, dataPath)) { string installedPath(file.c_str() + deviceTargetPath.length()); pushedFiles.push_back(PushedFile(file, installedPath)); } } } } Loading @@ -701,6 +736,13 @@ run_phases(vector<Target*> targets, const Options& options) printf(" %s\n", systemFiles[i].c_str()); } } if (pushedFiles.size() > 0){ print_info("Files to push:"); for (size_t i=0; i<pushedFiles.size(); i++) { printf(" %s\n", pushedFiles[i].file.filename.c_str()); printf(" --> %s\n", pushedFiles[i].dest.c_str()); } } if (installApks.size() > 0){ print_info("APKs to install:"); for (size_t i=0; i<installApks.size(); i++) { Loading Loading @@ -784,6 +826,25 @@ run_phases(vector<Target*> targets, const Options& options) } } // Push files if (pushedFiles.size() > 0) { print_status("Pushing files"); for (size_t i=0; i<pushedFiles.size(); i++) { const PushedFile& pushed = pushedFiles[i]; string dir = dirname(pushed.dest); if (dir.length() == 0 || dir == "/") { // This isn't really a file inside the data directory. Just skip it. continue; } // TODO: if (!apk.file.fileInfo.exists || apk.file.HasChanged()) err = run_adb("shell", "mkdir", "-p", dir.c_str(), NULL); check_error(err); err = run_adb("push", pushed.file.filename.c_str(), pushed.dest.c_str()); check_error(err); // pushed.installed = true; } } // Install APKs if (installApks.size() > 0) { print_status("Installing APKs"); Loading @@ -804,6 +865,74 @@ run_phases(vector<Target*> targets, const Options& options) // Actions // // Whether there have been any tests run, so we can print a summary. bool testsRun = false; // Run the native tests. // TODO: We don't have a good way of running these and capturing the output of // them live. It'll take some work. On the other hand, if they're gtest tests, // the output of gtest is not completely insane like the text output of the // instrumentation tests. So for now, we'll just live with that. for (size_t i=0; i<targets.size(); i++) { Target* target = targets[i]; if (target->test && target->module.HasClass(NATIVE_TESTS)) { // We don't have a clear signal from the build system which of the installed // files is actually the test, so we guess by looking for one with the same // leaf name as the module that is executable. for (size_t j=0; j<target->module.installed.size(); j++) { string filename = target->module.installed[j]; if (!starts_with(filename, dataPath)) { // Native tests go into the data directory. continue; } if (leafname(filename) != target->module.name) { // This isn't the test executable. continue; } if (!is_executable(filename)) { continue; } string installedPath(filename.c_str() + deviceTargetPath.length()); printf("the magic one is: %s\n", filename.c_str()); printf(" and it's installed at: %s\n", installedPath.c_str()); // Convert bit-style actions to gtest test filter arguments if (target->actions.size() > 0) { testsRun = true; target->testActionCount++; bool runAll = false; string filterArg("--gtest_filter="); for (size_t k=0; k<target->actions.size(); k++) { string actionString = target->actions[k]; if (actionString == "*") { runAll = true; } else { filterArg += actionString; if (k != target->actions.size()-1) { // We would otherwise have to worry about this condition // being true, and appending an extra ':', but we know that // if the extra action is "*", then we'll just run all and // won't use filterArg anyway, so just keep this condition // simple. filterArg += ':'; } } } if (runAll) { err = run_adb("shell", installedPath.c_str(), NULL); } else { err = run_adb("shell", installedPath.c_str(), filterArg.c_str(), NULL); } if (err == 0) { target->testPassCount++; } else { target->testFailCount++; } } } } } // Inspect the apks, and figure out what is an activity and what needs a test runner bool printedInspecting = false; vector<TestAction> testActions; Loading Loading @@ -872,6 +1001,7 @@ run_phases(vector<Target*> targets, const Options& options) TestResults testResults; if (testActions.size() > 0) { print_status("Running tests"); testsRun = true; for (size_t i=0; i<testActions.size(); i++) { TestAction& action = testActions[i]; testResults.SetCurrentAction(&action); Loading Loading @@ -969,7 +1099,7 @@ run_phases(vector<Target*> targets, const Options& options) // Tests bool hasErrors = false; if (testActions.size() > 0) { if (testsRun) { printf("%sRan tests:%s\n", g_escapeBold, g_escapeEndColor); size_t maxNameLength = 0; for (size_t i=0; i<targets.size(); i++) { Loading tools/bit/make.cpp +12 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,18 @@ make_cache_filename(const string& outDir) return filename + "/.bit_cache"; } bool Module::HasClass(const string& cl) { for (vector<string>::const_iterator c = classes.begin(); c != classes.end(); c++) { if (*c == cl) { return true; } } return false; } BuildVars::BuildVars(const string& outDir, const string& buildProduct, const string& buildVariant, const string& buildType) :m_filename(), Loading tools/bit/make.h +2 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ struct Module vector<string> classes; vector<string> paths; vector<string> installed; bool HasClass(const string& cl); }; /** Loading tools/bit/util.cpp +38 −0 Original line number Diff line number Diff line Loading @@ -254,4 +254,42 @@ read_file(const string& filename) return result; } bool is_executable(const string& filename) { int err; struct stat st; err = stat(filename.c_str(), &st); if (err != 0) { return false; } return (st.st_mode & S_IXUSR) != 0; } string dirname(const string& filename) { size_t slash = filename.rfind('/'); if (slash == string::npos) { return ""; } else if (slash == 0) { return "/"; } else { return string(filename, 0, slash); } } string leafname(const string& filename) { size_t slash = filename.rfind('/'); if (slash == string::npos) { return filename; } else if (slash == filename.length() - 1) { return ""; } else { return string(filename, slash + 1); } } tools/bit/util.h +5 −0 Original line number Diff line number Diff line Loading @@ -79,5 +79,10 @@ void split_lines(vector<string>* result, const string& str); string read_file(const string& filename); bool is_executable(const string& filename); string dirname(const string& filename); string leafname(const string& filename); #endif // UTIL_H Loading
tools/bit/main.cpp +133 −3 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ using namespace std; #define NATIVE_TESTS "NATIVE_TESTS" /** * An entry from the command line for something that will be built, installed, * and/or tested. Loading Loading @@ -132,6 +134,32 @@ InstallApk::InstallApk(const string& filename, bool always) { } struct PushedFile { TrackedFile file; string dest; PushedFile(); PushedFile(const PushedFile& that); PushedFile(const string& filename, const string& dest); ~PushedFile() {}; }; PushedFile::PushedFile() { } PushedFile::PushedFile(const PushedFile& that) :file(that.file), dest(that.dest) { } PushedFile::PushedFile(const string& f, const string& d) :file(f), dest(d) { } /** * Record for an test that is going to be launched. Loading Loading @@ -658,12 +686,14 @@ run_phases(vector<Target*> targets, const Options& options) } // Figure out whether we need to sync the system and which apks to install string systemPath = buildOut + "/target/product/" + buildDevice + "/system/"; string dataPath = buildOut + "/target/product/" + buildDevice + "/data/"; string deviceTargetPath = buildOut + "/target/product/" + buildDevice; string systemPath = deviceTargetPath + "/system/"; string dataPath = deviceTargetPath + "/data/"; bool syncSystem = false; bool alwaysSyncSystem = false; vector<string> systemFiles; vector<InstallApk> installApks; vector<PushedFile> pushedFiles; for (size_t i=0; i<targets.size(); i++) { Target* target = targets[i]; if (target->install) { Loading @@ -687,6 +717,11 @@ run_phases(vector<Target*> targets, const Options& options) installApks.push_back(InstallApk(file, !target->build)); continue; } // If it's a native test module, push it. if (target->module.HasClass(NATIVE_TESTS) && starts_with(file, dataPath)) { string installedPath(file.c_str() + deviceTargetPath.length()); pushedFiles.push_back(PushedFile(file, installedPath)); } } } } Loading @@ -701,6 +736,13 @@ run_phases(vector<Target*> targets, const Options& options) printf(" %s\n", systemFiles[i].c_str()); } } if (pushedFiles.size() > 0){ print_info("Files to push:"); for (size_t i=0; i<pushedFiles.size(); i++) { printf(" %s\n", pushedFiles[i].file.filename.c_str()); printf(" --> %s\n", pushedFiles[i].dest.c_str()); } } if (installApks.size() > 0){ print_info("APKs to install:"); for (size_t i=0; i<installApks.size(); i++) { Loading Loading @@ -784,6 +826,25 @@ run_phases(vector<Target*> targets, const Options& options) } } // Push files if (pushedFiles.size() > 0) { print_status("Pushing files"); for (size_t i=0; i<pushedFiles.size(); i++) { const PushedFile& pushed = pushedFiles[i]; string dir = dirname(pushed.dest); if (dir.length() == 0 || dir == "/") { // This isn't really a file inside the data directory. Just skip it. continue; } // TODO: if (!apk.file.fileInfo.exists || apk.file.HasChanged()) err = run_adb("shell", "mkdir", "-p", dir.c_str(), NULL); check_error(err); err = run_adb("push", pushed.file.filename.c_str(), pushed.dest.c_str()); check_error(err); // pushed.installed = true; } } // Install APKs if (installApks.size() > 0) { print_status("Installing APKs"); Loading @@ -804,6 +865,74 @@ run_phases(vector<Target*> targets, const Options& options) // Actions // // Whether there have been any tests run, so we can print a summary. bool testsRun = false; // Run the native tests. // TODO: We don't have a good way of running these and capturing the output of // them live. It'll take some work. On the other hand, if they're gtest tests, // the output of gtest is not completely insane like the text output of the // instrumentation tests. So for now, we'll just live with that. for (size_t i=0; i<targets.size(); i++) { Target* target = targets[i]; if (target->test && target->module.HasClass(NATIVE_TESTS)) { // We don't have a clear signal from the build system which of the installed // files is actually the test, so we guess by looking for one with the same // leaf name as the module that is executable. for (size_t j=0; j<target->module.installed.size(); j++) { string filename = target->module.installed[j]; if (!starts_with(filename, dataPath)) { // Native tests go into the data directory. continue; } if (leafname(filename) != target->module.name) { // This isn't the test executable. continue; } if (!is_executable(filename)) { continue; } string installedPath(filename.c_str() + deviceTargetPath.length()); printf("the magic one is: %s\n", filename.c_str()); printf(" and it's installed at: %s\n", installedPath.c_str()); // Convert bit-style actions to gtest test filter arguments if (target->actions.size() > 0) { testsRun = true; target->testActionCount++; bool runAll = false; string filterArg("--gtest_filter="); for (size_t k=0; k<target->actions.size(); k++) { string actionString = target->actions[k]; if (actionString == "*") { runAll = true; } else { filterArg += actionString; if (k != target->actions.size()-1) { // We would otherwise have to worry about this condition // being true, and appending an extra ':', but we know that // if the extra action is "*", then we'll just run all and // won't use filterArg anyway, so just keep this condition // simple. filterArg += ':'; } } } if (runAll) { err = run_adb("shell", installedPath.c_str(), NULL); } else { err = run_adb("shell", installedPath.c_str(), filterArg.c_str(), NULL); } if (err == 0) { target->testPassCount++; } else { target->testFailCount++; } } } } } // Inspect the apks, and figure out what is an activity and what needs a test runner bool printedInspecting = false; vector<TestAction> testActions; Loading Loading @@ -872,6 +1001,7 @@ run_phases(vector<Target*> targets, const Options& options) TestResults testResults; if (testActions.size() > 0) { print_status("Running tests"); testsRun = true; for (size_t i=0; i<testActions.size(); i++) { TestAction& action = testActions[i]; testResults.SetCurrentAction(&action); Loading Loading @@ -969,7 +1099,7 @@ run_phases(vector<Target*> targets, const Options& options) // Tests bool hasErrors = false; if (testActions.size() > 0) { if (testsRun) { printf("%sRan tests:%s\n", g_escapeBold, g_escapeEndColor); size_t maxNameLength = 0; for (size_t i=0; i<targets.size(); i++) { Loading
tools/bit/make.cpp +12 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,18 @@ make_cache_filename(const string& outDir) return filename + "/.bit_cache"; } bool Module::HasClass(const string& cl) { for (vector<string>::const_iterator c = classes.begin(); c != classes.end(); c++) { if (*c == cl) { return true; } } return false; } BuildVars::BuildVars(const string& outDir, const string& buildProduct, const string& buildVariant, const string& buildType) :m_filename(), Loading
tools/bit/make.h +2 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ struct Module vector<string> classes; vector<string> paths; vector<string> installed; bool HasClass(const string& cl); }; /** Loading
tools/bit/util.cpp +38 −0 Original line number Diff line number Diff line Loading @@ -254,4 +254,42 @@ read_file(const string& filename) return result; } bool is_executable(const string& filename) { int err; struct stat st; err = stat(filename.c_str(), &st); if (err != 0) { return false; } return (st.st_mode & S_IXUSR) != 0; } string dirname(const string& filename) { size_t slash = filename.rfind('/'); if (slash == string::npos) { return ""; } else if (slash == 0) { return "/"; } else { return string(filename, 0, slash); } } string leafname(const string& filename) { size_t slash = filename.rfind('/'); if (slash == string::npos) { return filename; } else if (slash == filename.length() - 1) { return ""; } else { return string(filename, slash + 1); } }
tools/bit/util.h +5 −0 Original line number Diff line number Diff line Loading @@ -79,5 +79,10 @@ void split_lines(vector<string>* result, const string& str); string read_file(const string& filename); bool is_executable(const string& filename); string dirname(const string& filename); string leafname(const string& filename); #endif // UTIL_H