Commit d27b8840 authored by jamesr's avatar jamesr Committed by Commit bot

Remove mojo/tools/, not needed in chromium

R=sky@chromium.org

Review URL: https://codereview.chromium.org/705703002

Cr-Commit-Position: refs/heads/master@{#302758}
parent 4df3c436
...@@ -12,7 +12,6 @@ group("mojo") { ...@@ -12,7 +12,6 @@ group("mojo") {
"//mojo/common", "//mojo/common",
"//mojo/public", "//mojo/public",
"//mojo/services", "//mojo/services",
"//mojo/tools/package_manager",
] ]
if (is_android) { if (is_android) {
...@@ -37,6 +36,5 @@ group("tests") { ...@@ -37,6 +36,5 @@ group("tests") {
"//mojo/public/cpp/environment/tests:mojo_public_environment_unittests", "//mojo/public/cpp/environment/tests:mojo_public_environment_unittests",
"//mojo/public/cpp/system/tests:mojo_public_system_unittests", "//mojo/public/cpp/system/tests:mojo_public_system_unittests",
"//mojo/public/cpp/utility/tests:mojo_public_utility_unittests", "//mojo/public/cpp/utility/tests:mojo_public_utility_unittests",
"//mojo/tools:message_generator",
] ]
} }
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
# to be built. # to be built.
'mojo_common_lib', 'mojo_common_lib',
'mojo_common_unittests', 'mojo_common_unittests',
'mojo_message_generator',
], ],
'conditions': [ 'conditions': [
['OS == "android"', { ['OS == "android"', {
...@@ -186,22 +185,6 @@ ...@@ -186,22 +185,6 @@
'bindings/js/waiting_callback.h', 'bindings/js/waiting_callback.h',
], ],
}, },
{
# GN version: //mojo/tools:message_generator
'target_name': 'mojo_message_generator',
'type': 'executable',
'dependencies': [
'../base/base.gyp:base',
'../testing/gtest.gyp:gtest',
'edk/mojo_edk.gyp:mojo_system_impl',
'mojo_common_lib',
'mojo_environment_chromium',
'public/mojo_public.gyp:mojo_cpp_bindings',
],
'sources': [
'tools/message_generator.cc',
],
},
], ],
'conditions': [ 'conditions': [
['OS=="android"', { ['OS=="android"', {
......
# Copyright 2014 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.
# GYP version: mojo/mojo_base.gyp:mojo_message_generator
executable("message_generator") {
testonly = true
output_name = "mojo_message_generator"
sources = [
"message_generator.cc",
]
deps = [
"//base",
"//mojo/common",
"//mojo/edk/system",
"//mojo/environment:chromium",
"//mojo/public/cpp/bindings",
"//testing/gtest",
]
}
#!/usr/bin/env python
# Copyright 2014 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.
import argparse
import os.path
import sys
from filecmp import dircmp
from shutil import rmtree
from tempfile import mkdtemp
_script_dir = os.path.dirname(os.path.abspath(__file__))
_mojo_dir = os.path.join(_script_dir, os.pardir)
_chromium_src_dir = os.path.join(_mojo_dir, os.pardir)
sys.path.insert(0, os.path.join(_mojo_dir, "public", "tools", "bindings",
"pylib"))
from mojom_tests.support.find_files import FindFiles
from mojom_tests.support.run_bindings_generator import RunBindingsGenerator
def _ProcessDircmpResults(results, verbose=False):
"""Prints results of directory comparison and returns true if they are
identical (note: the "left" directory should be the golden directory)."""
rv = not (bool(results.left_only) or bool(results.right_only) or \
bool(results.common_funny) or bool(results.funny_files) or \
bool(results.diff_files))
if verbose:
for f in results.left_only:
print "%s exists in golden directory but not in current output" % f
for f in results.right_only:
print "%s exists in current output but not in golden directory" % f
for f in results.common_funny + results.funny_files:
print "Unable to compare %s between golden directory and current output" \
% f
for f in results.diff_files:
print "%s differs between golden directory and current output" % f
for r in results.subdirs.values():
# If we're being verbose, check subdirectories even if we know that there
# are differences. Note that it's "... and rv" to avoid the short-circuit.
if rv or verbose:
rv = _ProcessDircmpResults(r, verbose=verbose) and rv
return rv
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--generate_golden_files", action="store_true",
help=("generate golden files (does not obliterate "
"directory"))
parser.add_argument("--keep_temp_dir", action="store_true",
help="don't delete the temporary directory")
parser.add_argument("--verbose", action="store_true",
help="spew excess verbiage")
parser.add_argument("golden_dir", metavar="GOLDEN_DIR",
help="directory with the golden files")
args = parser.parse_args()
if args.generate_golden_files:
if os.path.exists(args.golden_dir):
print "WARNING: golden directory %s already exists" % args.golden_dir
out_dir = args.golden_dir
else:
if not os.path.exists(args.golden_dir):
print "ERROR: golden directory %s does not exist" % args.golden_dir
return 1
out_dir = mkdtemp()
if args.verbose:
print "Generating files to %s ..." % out_dir
mojom_files = FindFiles(_mojo_dir, "*.mojom")
for mojom_file in mojom_files:
if args.verbose:
print " Processing %s ..." % os.path.relpath(mojom_file, _mojo_dir)
# TODO(vtl): This may wrong, since the path can be overridden in the .gyp
# file.
RunBindingsGenerator(out_dir, _mojo_dir, mojom_file,
["-I", os.path.abspath(_chromium_src_dir)])
if args.generate_golden_files:
return 0
identical = _ProcessDircmpResults(dircmp(args.golden_dir, out_dir, ignore=[]),
verbose=args.verbose)
if args.keep_temp_dir:
if args.verbose:
print "Not removing %s ..." % out_dir
else:
if args.verbose:
print "Removing %s ..." % out_dir
rmtree(out_dir)
if not identical:
print "FAILURE: current output differs from golden files"
return 1
print "SUCCESS: current output identical to golden files"
return 0
if __name__ == '__main__':
sys.exit(main())
# This file contains a list of Mojo gtest unit tests.
# Prepend * to indicate that results shouldn't be cached (e.g., if the test has
# other data dependencies).
# TODO(vtl): Add a way of specifying data dependencies instead.
# System tests:
mojo_system_unittests
# Public tests:
*mojo_public_bindings_unittests
mojo_public_environment_unittests
mojo_public_system_unittests
mojo_public_utility_unittests
# Non-system, non-public tests:
mojo_application_manager_unittests
mojo_common_unittests
mojo_view_manager_lib_unittests
# These tests currently crash. We should re-enable them when they pass.
#mojo_view_manager_unittests
mojo_surfaces_lib_unittests
# JavaScript tests:
*mojo_apps_js_unittests
*mojo_js_unittests
# Shell integration tests:
*mojo_shell_tests
"""Generate the org.chromium.mojo.bindings.Callbacks interface"""
import argparse
import sys
CALLBACK_TEMPLATE = ("""
/**
* A generic %d-argument callback.
*
* %s
*/
interface Callback%d<%s> {
/**
* Call the callback.
*/
public void call(%s);
}
""")
INTERFACE_TEMPLATE = (
"""// Copyright 2014 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.
// This file was generated using
// mojo/tools/generate_java_callback_interfaces.py
package org.chromium.mojo.bindings;
/**
* Contains a generic interface for callbacks.
*/
public interface Callbacks {
/**
* A generic callback.
*/
interface Callback0 {
/**
* Call the callback.
*/
public void call();
}
%s
}""")
def GenerateCallback(nb_args):
params = '\n * '.join(
['@param <T%d> the type of argument %d.' % (i+1, i+1)
for i in xrange(nb_args)])
template_parameters = ', '.join(['T%d' % (i+1) for i in xrange(nb_args)])
callback_parameters = ', '.join(['T%d arg%d' % ((i+1), (i+1))
for i in xrange(nb_args)])
return CALLBACK_TEMPLATE % (nb_args, params, nb_args, template_parameters,
callback_parameters)
def main():
parser = argparse.ArgumentParser(
description="Generate org.chromium.mojo.bindings.Callbacks")
parser.add_argument("max_args", nargs=1, type=int,
help="maximal number of arguments to generate callbacks for")
args = parser.parse_args()
max_args = args.max_args[0]
print INTERFACE_TEMPLATE % ''.join([GenerateCallback(i+1)
for i in xrange(max_args)])
return 0
if __name__ == "__main__":
sys.exit(main())
// Copyright 2014 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.
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "mojo/public/cpp/bindings/lib/message_builder.h"
#include "mojo/public/cpp/bindings/lib/message_internal.h"
#include "mojo/public/cpp/bindings/message.h"
// This file is used to generate various files corresponding to mojo
// messages. The various binding implementations can parse these to verify they
// correctly decode messages.
//
// The output consists of each byte of the message encoded in a hex string with
// a newline after it.
namespace mojo {
namespace {
std::string BinaryToHex(const base::StringPiece& piece) {
std::string result("// File generated by mojo_message_generator.\n");;
result.reserve(result.size() + (piece.size() * 5));
for (size_t i = 0; i < piece.size(); ++i)
base::StringAppendF(&result, "0X%.2X\n", static_cast<int>(piece.data()[i]));
return result;
}
void WriteMessageToFile(const Message& message, const base::FilePath& path) {
const std::string hex_message(BinaryToHex(
base::StringPiece(reinterpret_cast<const char*>(message.data()),
message.data_num_bytes())));
CHECK_EQ(static_cast<int>(hex_message.size()),
base::WriteFile(path, hex_message.data(),
static_cast<int>(hex_message.size())));
}
// Generates a message of type MessageData. The message uses the name 21,
// with 4 bytes of payload: 0x9, 0x8, 0x7, 0x6.
void GenerateMessageDataMessage() {
internal::MessageBuilder builder(static_cast<uint32_t>(21),
static_cast<size_t>(4));
char* data = static_cast<char*>(builder.buffer()->Allocate(4));
DCHECK(data);
data[0] = 9;
data[1] = 8;
data[2] = 7;
data[3] = 6;
Message message;
builder.Finish(&message);
WriteMessageToFile(message,
base::FilePath(FILE_PATH_LITERAL("message_data")));
}
} // namespace
} // namespace mojo
int main(int argc, char** argv) {
mojo::GenerateMessageDataMessage();
return 0;
}
#!/bin/bash
# Copyright 2013 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.
# This a simple script to make building/testing Mojo components easier (on
# Linux).
# TODO(vtl): Maybe make the test runner smart and not run unchanged test
# binaries.
# TODO(vtl) Maybe also provide a way to pass command-line arguments to the test
# binaries.
do_help() {
cat << EOF
Usage: $(basename "$0") [command|option ...]
command should be one of:
build - Build.
test - Run unit tests (does not build).
perftest - Run perf tests (does not build).
pytest - Run Python unit tests (does not build).
gn - Run gn for mojo (does not sync).
sync - Sync using gclient (does not run gn).
show-bash-alias - Outputs an appropriate bash alias for mojob. In bash do:
\$ eval \`mojo/tools/mojob.sh show-bash-alias\`
option (which will only apply to commands which follow) should be one of:
General options (specify before everything):
--debug / --release / --debug-and-release - Debug (default) build /
Release build / Debug and Release builds.
gn options (specify before gn):
--clang / --gcc - Use clang (default) / gcc.
--use-goma / --no-use-goma - Use goma (if \$GOMA_DIR is set or \$HOME/goma
exists; default) / don't use goma.
Note: It will abort on the first failure (if any).
EOF
}
get_gn_arg_value() {
grep -m 1 "^[[:space:]]*\<$2\>" "$1/args.gn" | \
sed -n 's/.* = "\?\([^"]*\)"\?$/\1/p'
}
do_build() {
echo "Building in out/$1 ..."
if [ "$(get_gn_arg_value "out/$1" use_goma)" = "true" ]; then
# Use the configured goma directory.
local goma_dir="$(get_gn_arg_value "out/$1" goma_dir)"
echo "Ensuring goma (in ${goma_dir}) started ..."
"${goma_dir}/goma_ctl.py" ensure_start
ninja -j 1000 -l 100 -C "out/$1" mojo || exit 1
else
ninja -C "out/$1" mojo || exit 1
fi
}
do_unittests() {
echo "Running unit tests in out/$1 ..."
mojo/tools/test_runner.py mojo/tools/data/unittests "out/$1" \
mojob_test_successes || exit 1
}
do_perftests() {
echo "Running perf tests in out/$1 ..."
"out/$1/mojo_public_system_perftests" || exit 1
}
do_gn() {
local gn_args="$(make_gn_args $1)"
echo "Running gn with --args=\"${gn_args}\" ..."
gn gen --args="${gn_args}" "out/$1"
}
do_sync() {
# Note: sync only (with hooks, but no gyp-ing).
GYP_CHROMIUM_NO_ACTION=1 gclient sync || exit 1
}
# Valid values: Debug, Release, or Debug_and_Release.
BUILD_TYPE=Debug_and_Release
should_do_Debug() {
test "$BUILD_TYPE" = Debug -o "$BUILD_TYPE" = Debug_and_Release
}
should_do_Release() {
test "$BUILD_TYPE" = Release -o "$BUILD_TYPE" = Debug_and_Release
}
# Valid values: clang or gcc.
COMPILER=clang
# Valid values: auto or disabled.
GOMA=auto
make_gn_args() {
local args=()
# TODO(vtl): It's a bit of a hack to infer the build type from the output
# directory name, but it's what we have right now (since we support "debug and
# release" mode).
case "$1" in
Debug)
# (Default.)
;;
Release)
args+=("is_debug=false")
;;
esac
case "$COMPILER" in
clang)
# (Default.)
;;
gcc)
args+=("is_clang=false")
;;
esac
case "$GOMA" in
auto)
if [ -v GOMA_DIR ]; then
args+=("use_goma=true" "goma_dir=\"${GOMA_DIR}\"")
elif [ -d "${HOME}/goma" ]; then
args+=("use_goma=true" "goma_dir=\"${HOME}/goma\"")
else
: # (Default.)
fi
;;
disabled)
# (Default.)
;;
esac
echo "${args[*]}"
}
# We're in src/mojo/tools. We want to get to src.
cd "$(realpath "$(dirname "$0")")/../.."
if [ $# -eq 0 ]; then
do_help
exit 0
fi
for arg in "$@"; do
case "$arg" in
# Commands -----------------------------------------------------------------
help|--help)
do_help
exit 0
;;
build)
should_do_Debug && do_build Debug
should_do_Release && do_build Release
;;
test)
should_do_Debug && do_unittests Debug
should_do_Release && do_unittests Release
;;
perftest)
should_do_Debug && do_perftests Debug
should_do_Release && do_perftests Release
;;
gn)
should_do_Debug && do_gn Debug
should_do_Release && do_gn Release
;;
sync)
do_sync
;;
show-bash-alias)
# You want to type something like:
# alias mojob=\
# '"$(pwd | sed '"'"'s/\(.*\/src\).*/\1/'"'"')/mojo/tools/mojob.sh"'
# This is quoting hell, so we simply escape every non-alphanumeric
# character.
echo alias\ mojob\=\'\"\$\(pwd\ \|\ sed\ \'\"\'\"\'s\/\\\(\.\*\\\/src\\\)\
\.\*\/\\1\/\'\"\'\"\'\)\/mojo\/tools\/mojob\.sh\"\'
;;
# Options ------------------------------------------------------------------
--debug)
BUILD_TYPE=Debug
;;
--release)
BUILD_TYPE=Release
;;
--debug-and-release)
BUILD_TYPE=Debug_and_Release
;;
--clang)
COMPILER=clang
;;
--gcc)
COMPILER=gcc
;;
--use-goma)
GOMA=auto
;;
--no-use-goma)
GOMA=disabled
;;
*)
echo "Unknown command \"${arg}\". Try \"$(basename "$0") help\"."
exit 1
;;
esac
done
exit 0
#!/bin/bash
# Copyright 2014 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.
# This a simple script to make running Mojo shell easier (on Linux).
DIRECTORY="$(dirname "$0")"/../../out/Debug
PORT=$(($RANDOM % 8192 + 2000))
do_help() {
cat << EOF
Usage: $(basename "$0") [-d DIRECTORY] [-|--] <mojo_shell arguments ...>
DIRECTORY defaults to $DIRECTORY.
Example:
$(basename "$0") mojo:sample_app
EOF
}
kill_http_server() {
echo "Killing SimpleHTTPServer ..."
kill $HTTP_SERVER_PID
wait $HTTP_SERVER_PID
}
while [ $# -gt 0 ]; do
case "$1" in
-h|--help)
do_help
exit 0
;;
-d)
shift
if [ $# -eq 0 ]; then
do_help
exit 1
fi
DIRECTORY="$1"
;;
--show-bash-alias)
echo alias\ mojosh\=\'\"\$\(pwd\ \|\ sed\ \'\"\'\"\'s\/\\\(\.\*\\\/src\\\
\)\.\*\/\\1\/\'\"\'\"\'\)\/mojo\/tools\/mojosh\.sh\"\'
exit 0
;;
# Separate arguments to mojo_shell (e.g., in case you want to pass it -d).
-|--)
shift
break
;;
*)
break
;;
esac
shift
done
echo "Base directory: $DIRECTORY"
echo "Running SimpleHTTPServer in directory $DIRECTORY/lib on port $PORT"
cd $DIRECTORY/lib || exit 1
python -m SimpleHTTPServer $PORT &
# Kill the HTTP server on exit (even if the user kills everything using ^C).
HTTP_SERVER_PID=$!
trap kill_http_server EXIT
cd ..
echo "Running:"
echo "./mojo_shell --origin=http://127.0.0.1:$PORT --disable-cache $*"
./mojo_shell --origin=http://127.0.0.1:$PORT --disable-cache $*
# Copyright 2014 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.
shared_library("package_manager") {
output_name = "mojo_package_manager"
sources = [
"manifest.cc",
"manifest.h",
"package_fetcher.cc",
"package_fetcher.h",
"package_manager.cc",
"package_manager_application.cc",
"package_manager_application.h",
"unpacker.cc",
"unpacker.h",
]
deps = [
"//base",
"//mojo/application",
"//mojo/public/c/system:for_shared_library",
"//mojo/public/cpp/utility",
"//mojo/services/public/interfaces/network",
"//third_party/zlib:zip",
"//url",
]
}
include_rules = [
'+third_party/zlib',
]
// Copyright 2014 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.
#include "mojo/tools/package_manager/manifest.h"
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/values.h"
#include "url/gurl.h"
namespace mojo {
Manifest::Manifest() {
}
Manifest::~Manifest() {
}
bool Manifest::Parse(const std::string& str, std::string* err_msg) {
int err_code = base::JSONReader::JSON_NO_ERROR;
scoped_ptr<base::Value> root(base::JSONReader::ReadAndReturnError(
str,
base::JSON_ALLOW_TRAILING_COMMAS,
&err_code, err_msg));
if (err_code != base::JSONReader::JSON_NO_ERROR)
return false;
const base::DictionaryValue* root_dict;
if (!root->GetAsDictionary(&root_dict)) {
*err_msg = "Manifest is not a dictionary.";
return false;
}
if (!PopulateDeps(root_dict, err_msg))
return false;
return true;
}
bool Manifest::ParseFromFile(const base::FilePath& file_name,
std::string* err_msg) {
std::string data;
if (!base::ReadFileToString(file_name, &data)) {
*err_msg = "Couldn't read manifest file " + file_name.AsUTF8Unsafe();
return false;
}
return Parse(data, err_msg);
}
bool Manifest::PopulateDeps(const base::DictionaryValue* root,
std::string* err_msg) {
const base::Value* deps_value;
if (!root->Get("deps", &deps_value))
return true; // No deps, that's OK.
const base::ListValue* deps;
if (!deps_value->GetAsList(&deps)) {
*err_msg = "Deps is not a list. Should be \"deps\": [ \"...\", \"...\" ]";
return false;
}
deps_.reserve(deps->GetSize());
for (size_t i = 0; i < deps->GetSize(); i++) {
std::string cur_dep;
if (!deps->GetString(i, &cur_dep)) {
*err_msg = "Dependency list item wasn't a string.";
return false;
}
GURL cur_url(cur_dep);
if (!cur_url.is_valid()) {
*err_msg = "Dependency entry isn't a valid URL: " + cur_dep;
return false;
}
deps_.push_back(cur_url);
}
return true;
}
} // namespace mojo
// Copyright 2014 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.
#ifndef MOJO_TOOLS_PACKAGE_MANAGER_MANIFEST_H_
#define MOJO_TOOLS_PACKAGE_MANAGER_MANIFEST_H_
#include <string>
#include <vector>
#include "mojo/public/cpp/system/macros.h"
class GURL;
namespace base {
class DictionaryValue;
class FilePath;
}
namespace mojo {
class Manifest {
public:
Manifest();
~Manifest();
// Parses the manifest from raw data. Returns true on success. On failure,
// populates the "err_msg" string with an error.
bool Parse(const std::string& str, std::string* err_msg);
// Like Parse but reads the data from a file.
bool ParseFromFile(const base::FilePath& file_name, std::string* err_msg);
const std::vector<GURL>& deps() const { return deps_; }
private:
bool PopulateDeps(const base::DictionaryValue* root, std::string* err_msg);
std::vector<GURL> deps_;
MOJO_DISALLOW_COPY_AND_ASSIGN(Manifest);
};
} // namespace mojo
#endif // MOJO_TOOLS_PACKAGE_MANAGER_MANIFEST_H_
// Copyright 2014 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.
#include "mojo/tools/package_manager/package_fetcher.h"
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "mojo/services/public/interfaces/network/url_loader.mojom.h"
namespace mojo {
PackageFetcher::PackageFetcher(NetworkService* network_service,
PackageFetcherDelegate* delegate,
const GURL& url)
: delegate_(delegate),
url_(url) {
network_service->CreateURLLoader(GetProxy(&loader_));
URLRequestPtr request(URLRequest::New());
request->url = url.spec();
request->auto_follow_redirects = true;
loader_->Start(request.Pass(),
base::Bind(&PackageFetcher::OnReceivedResponse,
base::Unretained(this)));
}
PackageFetcher::~PackageFetcher() {
}
void PackageFetcher::OnReceivedResponse(URLResponsePtr response) {
if (response->error) {
printf("Got error %d (%s) for %s\n",
response->error->code,
response->error->description.get().c_str(),
url_.spec().c_str());
delegate_->FetchFailed(url_);
return;
}
if (!base::CreateTemporaryFile(&output_file_name_)) {
delegate_->FetchFailed(url_);
return;
}
output_file_.Initialize(output_file_name_,
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
if (!output_file_.IsValid()) {
base::DeleteFile(output_file_name_, false);
delegate_->FetchFailed(url_);
// Danger: may be deleted now.
return;
}
body_ = response->body.Pass();
ReadData(MOJO_RESULT_OK);
// Danger: may be deleted now.
}
void PackageFetcher::ReadData(MojoResult) {
char buf[4096];
uint32_t num_bytes = sizeof(buf);
MojoResult result = ReadDataRaw(body_.get(), buf, &num_bytes,
MOJO_READ_DATA_FLAG_NONE);
if (result == MOJO_RESULT_SHOULD_WAIT) {
WaitToReadMore();
} else if (result == MOJO_RESULT_OK) {
if (output_file_.WriteAtCurrentPos(buf, num_bytes) !=
static_cast<int>(num_bytes)) {
// Clean up the output file.
output_file_.Close();
base::DeleteFile(output_file_name_, false);
delegate_->FetchFailed(url_);
// Danger: may be deleted now.
return;
}
WaitToReadMore();
} else if (result == MOJO_RESULT_FAILED_PRECONDITION) {
// Done.
output_file_.Close();
delegate_->FetchSucceeded(url_, output_file_name_);
// Danger: may be deleted now.
}
}
void PackageFetcher::WaitToReadMore() {
handle_watcher_.Start(
body_.get(),
MOJO_HANDLE_SIGNAL_READABLE,
MOJO_DEADLINE_INDEFINITE,
base::Bind(&PackageFetcher::ReadData, base::Unretained(this)));
}
} // namespace mojo
// Copyright 2014 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.
#ifndef MOJO_TOOLS_PACKAGE_MANAGER_FETCHER_H_
#define MOJO_TOOLS_PACKAGE_MANAGER_FETCHER_H_
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "mojo/common/handle_watcher.h"
#include "mojo/public/cpp/system/macros.h"
#include "mojo/services/public/interfaces/network/network_service.mojom.h"
#include "mojo/services/public/interfaces/network/url_loader.mojom.h"
#include "url/gurl.h"
namespace base {
class FilePath;
} // namespace base
namespace mojo {
class PackageFetcherDelegate;
class PackageFetcher {
public:
PackageFetcher(NetworkService* network_service,
PackageFetcherDelegate* delegate,
const GURL& url);
virtual ~PackageFetcher();
private:
void OnReceivedResponse(URLResponsePtr response);
void ReadData(MojoResult);
void WaitToReadMore();
PackageFetcherDelegate* delegate_;
// URL of the package.
GURL url_;
URLLoaderPtr loader_;
// Valid once file has started streaming.
ScopedDataPipeConsumerHandle body_;
common::HandleWatcher handle_watcher_;
base::FilePath output_file_name_;
base::File output_file_;
MOJO_DISALLOW_COPY_AND_ASSIGN(PackageFetcher);
};
class PackageFetcherDelegate {
public:
virtual void FetchSucceeded(const GURL& url, const base::FilePath& name) = 0;
virtual void FetchFailed(const GURL& url) = 0;
};
} // namespace mojo
#endif // MOJO_TOOLS_PACKAGE_MANAGER_FETCHER_H_
// Copyright 2014 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.
#include "mojo/application/application_runner_chromium.h"
#include "mojo/public/c/system/main.h"
#include "mojo/tools/package_manager/package_manager_application.h"
MojoResult MojoMain(MojoHandle shell_handle) {
mojo::ApplicationRunnerChromium runner(new mojo::PackageManagerApplication);
return runner.Run(shell_handle);
}
// Copyright 2014 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.
#include "mojo/tools/package_manager/package_manager_application.h"
#include "base/files/file_util.h"
#include "mojo/tools/package_manager/manifest.h"
#include "mojo/tools/package_manager/unpacker.h"
#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
#include "mojo/public/cpp/application/application_impl.h"
namespace mojo {
namespace {
const base::FilePath::CharType kManifestFileName[] =
FILE_PATH_LITERAL("manifest.json");
} // namespace
PackageManagerApplication::PendingLoad::PendingLoad() {
}
PackageManagerApplication::PendingLoad::~PendingLoad() {
}
PackageManagerApplication::PackageManagerApplication() {
}
PackageManagerApplication::~PackageManagerApplication() {
STLDeleteContainerPairSecondPointers(pending_.begin(), pending_.end());
}
void PackageManagerApplication::Initialize(ApplicationImpl* app) {
app->ConnectToService("mojo:network_service", &network_service_);
printf("Enter URL> ");
char buf[1024];
if (scanf("%1023s", buf) != 1) {
printf("No input, exiting\n");
base::MessageLoop::current()->Quit();
return;
}
GURL url(buf);
if (!url.is_valid()) {
printf("Invalid URL\n");
base::MessageLoop::current()->Quit();
return;
}
StartLoad(url);
}
void PackageManagerApplication::StartLoad(const GURL& url) {
if (completed_.find(url) != completed_.end() ||
pending_.find(url) != pending_.end())
return; // Already loaded or are loading this one.
PendingLoad* load = new PendingLoad;
load->fetcher.reset(new mojo::PackageFetcher(
network_service_.get(), this, url));
pending_[url] = load;
}
void PackageManagerApplication::LoadDeps(const Manifest& manifest) {
for (size_t i = 0; i < manifest.deps().size(); i++)
StartLoad(manifest.deps()[i]);
}
void PackageManagerApplication::PendingLoadComplete(const GURL& url) {
pending_.erase(pending_.find(url));
completed_.insert(url);
if (pending_.empty())
base::MessageLoop::current()->Quit();
}
void PackageManagerApplication::FetchSucceeded(
const GURL& url,
const base::FilePath& name) {
Unpacker unpacker;
if (!unpacker.Unpack(name)) {
base::DeleteFile(name, false);
printf("Failed to unpack\n");
PendingLoadComplete(url);
return;
}
// The downloaded .zip file is no longer necessary.
base::DeleteFile(name, false);
// Load the manifest.
base::FilePath manifest_path = unpacker.dir().Append(kManifestFileName);
Manifest manifest;
std::string err_msg;
if (!manifest.ParseFromFile(manifest_path, &err_msg)) {
printf("%s\n", err_msg.c_str());
PendingLoadComplete(url);
return;
}
// Enqueue loads for any deps.
LoadDeps(manifest);
printf("Loaded %s\n", url.spec().c_str());
PendingLoadComplete(url);
}
void PackageManagerApplication::FetchFailed(const GURL& url) {
PendingLoadComplete(url);
}
} // namespace mojo
// Copyright 2014 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.
#ifndef MOJO_PACKAGE_MANAGER_PACKAGE_MANAGER_APPLICATION_H_
#define MOJO_PACKAGE_MANAGER_PACKAGE_MANAGER_APPLICATION_H_
#include <map>
#include <set>
#include "mojo/public/cpp/application/application_delegate.h"
#include "mojo/public/cpp/application/interface_factory.h"
#include "mojo/public/cpp/system/macros.h"
#include "mojo/services/public/interfaces/network/network_service.mojom.h"
#include "mojo/tools/package_manager/package_fetcher.h"
namespace mojo {
class Manifest;
class PackageManagerApplication
: public ApplicationDelegate,
public PackageFetcherDelegate {
public:
PackageManagerApplication();
virtual ~PackageManagerApplication();
private:
struct PendingLoad {
PendingLoad();
~PendingLoad();
scoped_ptr<PackageFetcher> fetcher;
};
typedef std::map<GURL, PendingLoad*> PendingLoadMap;
void StartLoad(const GURL& url);
void LoadDeps(const Manifest& manifest);
// Deletes the pending load entry for the given URL and possibly exits the
// message loop if all loads are done.
void PendingLoadComplete(const GURL& url);
// ApplicationDelegate implementation.
virtual void Initialize(ApplicationImpl* app) override;
// PackageFetcher.
virtual void FetchSucceeded(const GURL& url,
const base::FilePath& name) override;
virtual void FetchFailed(const GURL& url) override;
mojo::NetworkServicePtr network_service_;
PendingLoadMap pending_; // Owning pointers.
std::set<GURL> completed_;
MOJO_DISALLOW_COPY_AND_ASSIGN(PackageManagerApplication);
};
} // namespace mojo
#endif // MOJO_PACKAGE_MANAGER_PACKAGE_MANAGER_APPLICATION_H
// Copyright 2014 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.
#include "mojo/tools/package_manager/unpacker.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "third_party/zlib/google/zip.h"
namespace mojo {
Unpacker::Unpacker() {
}
Unpacker::~Unpacker() {
if (!dir_.empty())
DeleteFile(dir_, true);
}
bool Unpacker::Unpack(const base::FilePath& zip_file) {
DCHECK(zip_file_.empty());
zip_file_ = zip_file;
DCHECK(dir_.empty());
if (!CreateNewTempDirectory(base::FilePath::StringType(), &dir_))
return false;
if (!zip::Unzip(zip_file, dir_)) {
dir_ = base::FilePath();
return false;
}
return true;
}
} // namespace mojo
// Copyright 2014 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.
#ifndef MOJO_TOOLS_PACKAGE_MANAGER_UNPACKER_H_
#define MOJO_TOOLS_PACKAGE_MANAGER_UNPACKER_H_
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
// Unzips a package into a temporary folder. The temporary folder will be
// deleted when the object is destroyed.
//
// In the future, this class would probably manage doing the unzip operation on
// a background thread.
class Unpacker {
public:
Unpacker();
~Unpacker();
// Actually does the unpacking, returns true on success.
bool Unpack(const base::FilePath& zip_file);
// The root directory where the package has been unpacked.
const base::FilePath& dir() const { return dir_; }
private:
base::FilePath zip_file_;
base::FilePath dir_;
MOJO_DISALLOW_COPY_AND_ASSIGN(Unpacker);
};
} // namespace mojo
#endif // MOJO_TOOLS_PACKAGE_MANAGER_UNPACKER_H_
# Copyright 2014 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.
import argparse
import json
import os
import sys
import time
import unittest
class MojoPythonTestRunner(object):
"""Helper class to run python tests on the bots."""
def __init__(self, test_dir):
self._test_dir = test_dir
def run(self):
parser = argparse.ArgumentParser()
parser.usage = 'run_mojo_python_tests.py [options] [tests...]'
parser.add_argument('-v', '--verbose', action='count', default=0)
parser.add_argument('--metadata', action='append', default=[],
help=('optional key=value metadata that will be stored '
'in the results files (can be used for revision '
'numbers, etc.)'))
parser.add_argument('--write-full-results-to', metavar='FILENAME',
action='store',
help='path to write the list of full results to.')
parser.add_argument('tests', nargs='*')
self.add_custom_commandline_options(parser)
args = parser.parse_args()
self.apply_customization(args)
bad_metadata = False
for val in args.metadata:
if '=' not in val:
print >> sys.stderr, ('Error: malformed metadata "%s"' % val)
bad_metadata = True
if bad_metadata:
print >> sys.stderr
parser.print_help()
return 2
chromium_src_dir = os.path.join(os.path.dirname(__file__),
os.pardir,
os.pardir,
os.pardir)
loader = unittest.loader.TestLoader()
print "Running Python unit tests under %s..." % self._test_dir
pylib_dir = os.path.abspath(os.path.join(chromium_src_dir, self._test_dir))
if args.tests:
if pylib_dir not in sys.path:
sys.path.append(pylib_dir)
suite = unittest.TestSuite()
for test_name in args.tests:
suite.addTests(loader.loadTestsFromName(test_name))
else:
suite = loader.discover(pylib_dir, pattern='*_unittest.py')
runner = unittest.runner.TextTestRunner(verbosity=(args.verbose + 1))
result = runner.run(suite)
full_results = _FullResults(suite, result, args.metadata)
if args.write_full_results_to:
with open(args.write_full_results_to, 'w') as fp:
json.dump(full_results, fp, indent=2)
fp.write("\n")
return 0 if result.wasSuccessful() else 1
def add_custom_commandline_options(self, parser):
"""Allow to add custom option to the runner script."""
pass
def apply_customization(self, args):
"""Allow to apply any customization to the runner."""
pass
TEST_SEPARATOR = '.'
def _FullResults(suite, result, metadata):
"""Convert the unittest results to the Chromium JSON test result format.
This matches run-webkit-tests (the layout tests) and the flakiness dashboard.
"""
full_results = {}
full_results['interrupted'] = False
full_results['path_delimiter'] = TEST_SEPARATOR
full_results['version'] = 3
full_results['seconds_since_epoch'] = time.time()
for md in metadata:
key, val = md.split('=', 1)
full_results[key] = val
all_test_names = _AllTestNames(suite)
failed_test_names = _FailedTestNames(result)
full_results['num_failures_by_type'] = {
'FAIL': len(failed_test_names),
'PASS': len(all_test_names) - len(failed_test_names),
}
full_results['tests'] = {}
for test_name in all_test_names:
value = {}
value['expected'] = 'PASS'
if test_name in failed_test_names:
value['actual'] = 'FAIL'
value['is_unexpected'] = True
else:
value['actual'] = 'PASS'
_AddPathToTrie(full_results['tests'], test_name, value)
return full_results
def _AllTestNames(suite):
test_names = []
# _tests is protected pylint: disable=W0212
for test in suite._tests:
if isinstance(test, unittest.suite.TestSuite):
test_names.extend(_AllTestNames(test))
else:
test_names.append(test.id())
return test_names
def _FailedTestNames(result):
return set(test.id() for test, _ in result.failures + result.errors)
def _AddPathToTrie(trie, path, value):
if TEST_SEPARATOR not in path:
trie[path] = value
return
directory, rest = path.split(TEST_SEPARATOR, 1)
if directory not in trie:
trie[directory] = {}
_AddPathToTrie(trie[directory], rest, value)
# Copyright 2014 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.
import logging
import subprocess
import sys
from hashlib import sha256
from os.path import basename, realpath
_logging = logging.getLogger()
# Based on/taken from
# http://code.activestate.com/recipes/578231-probably-the-fastest-memoization-decorator-in-the-/
# (with cosmetic changes).
def _memoize(f):
"""Memoization decorator for a function taking a single argument."""
class Memoize(dict):
def __missing__(self, key):
rv = self[key] = f(key)
return rv
return Memoize().__getitem__
@_memoize
def _file_hash(filename):
"""Returns a string representing the hash of the given file."""
_logging.debug("Hashing %s ...", filename)
rv = subprocess.check_output(['sha256sum', '-b', filename]).split(None, 1)[0]
_logging.debug(" => %s", rv)
return rv
@_memoize
def _get_dependencies(filename):
"""Returns a list of filenames for files that the given file depends on."""
_logging.debug("Getting dependencies for %s ...", filename)
lines = subprocess.check_output(['ldd', filename]).splitlines()
rv = []
for line in lines:
i = line.find('/')
if i < 0:
_logging.debug(" => no file found in line: %s", line)
continue
rv.append(line[i:].split(None, 1)[0])
_logging.debug(" => %s", rv)
return rv
def transitive_hash(filename):
"""Returns a string that represents the "transitive" hash of the given
file. The transitive hash is a hash of the file and all the shared libraries
on which it depends (done in an order-independent way)."""
hashes = set()
to_hash = [filename]
while to_hash:
current_filename = realpath(to_hash.pop())
current_hash = _file_hash(current_filename)
if current_hash in hashes:
_logging.debug("Already seen %s (%s) ...", current_filename, current_hash)
continue
_logging.debug("Haven't seen %s (%s) ...", current_filename, current_hash)
hashes.add(current_hash)
to_hash.extend(_get_dependencies(current_filename))
return sha256('|'.join(sorted(hashes))).hexdigest()
def main(argv):
logging.basicConfig()
# Uncomment to debug:
# _logging.setLevel(logging.DEBUG)
if len(argv) < 2:
print """\
Usage: %s [file] ...
Prints the \"transitive\" hash of each (executable) file. The transitive
hash is a hash of the file and all the shared libraries on which it
depends (done in an order-independent way).""" % basename(argv[0])
return 0
rv = 0
for filename in argv[1:]:
try:
print transitive_hash(filename), filename
except:
print "ERROR", filename
rv = 1
return rv
if __name__ == '__main__':
sys.exit(main(sys.argv))
#!/usr/bin/env python
# Copyright 2014 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.
import os
import sys
_script_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, os.path.join(_script_dir, "pylib"))
from mojo_python_tests_runner import MojoPythonTestRunner
class PythonBindingsTestRunner(MojoPythonTestRunner):
def add_custom_commandline_options(self, parser):
parser.add_argument('--build-dir', action='store',
help='path to the build output directory')
def apply_customization(self, args):
if args.build_dir:
python_build_dir = os.path.join(args.build_dir, 'python')
if python_build_dir not in sys.path:
sys.path.append(python_build_dir)
python_gen_dir = os.path.join(
args.build_dir,
'gen', 'mojo', 'public', 'interfaces', 'bindings', 'tests')
if python_gen_dir not in sys.path:
sys.path.append(python_gen_dir)
def main():
runner = PythonBindingsTestRunner(os.path.join('mojo', 'python', 'tests'))
sys.exit(runner.run())
if __name__ == '__main__':
sys.exit(main())
#!/usr/bin/env python
# Copyright 2014 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.
import os
import sys
_script_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, os.path.join(_script_dir, "pylib"))
from mojo_python_tests_runner import MojoPythonTestRunner
def main():
runner = MojoPythonTestRunner(os.path.join('mojo', 'public', 'tools',
'bindings', 'pylib'))
sys.exit(runner.run())
if __name__ == '__main__':
sys.exit(main())
#!/usr/bin/env python
# Copyright 2014 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.
"""A "smart" test runner for gtest unit tests (that caches successes)."""
import logging
import os
import subprocess
import sys
_logging = logging.getLogger()
_script_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, os.path.join(_script_dir, "pylib"))
from transitive_hash import transitive_hash
def main(argv):
logging.basicConfig()
# Uncomment to debug:
# _logging.setLevel(logging.DEBUG)
if len(argv) < 3 or len(argv) > 4:
print "Usage: %s gtest_list_file root_dir [successes_cache_file]" % \
os.path.basename(argv[0])
return 0 if len(argv) < 2 else 1
_logging.debug("Test list file: %s", argv[1])
with open(argv[1], 'rb') as f:
gtest_list = [y for y in [x.strip() for x in f.readlines()] \
if y and y[0] != '#']
_logging.debug("Test list: %s" % gtest_list)
print "Running tests in directory: %s" % argv[2]
os.chdir(argv[2])
if len(argv) == 4 and argv[3]:
successes_cache_filename = argv[3]
print "Successes cache file: %s" % successes_cache_filename
else:
successes_cache_filename = None
print "No successes cache file (will run all tests unconditionally)"
if successes_cache_filename:
# This file simply contains a list of transitive hashes of tests that
# succeeded.
try:
_logging.debug("Trying to read successes cache file: %s",
successes_cache_filename)
with open(argv[3], 'rb') as f:
successes = set([x.strip() for x in f.readlines()])
_logging.debug("Successes: %s", successes)
except:
# Just assume that it didn't exist, or whatever.
print "Failed to read successes cache file %s (will create)" % argv[3]
successes = set()
# Run gtests with color if we're on a TTY (and we're not being told explicitly
# what to do).
if sys.stdout.isatty() and 'GTEST_COLOR' not in os.environ:
_logging.debug("Setting GTEST_COLOR=yes")
os.environ['GTEST_COLOR'] = 'yes'
# TODO(vtl): We may not close this file on failure.
successes_cache_file = open(successes_cache_filename, 'ab') \
if successes_cache_filename else None
for gtest in gtest_list:
if gtest[0] == '*':
gtest = gtest[1:]
_logging.debug("%s is marked as non-cacheable" % gtest)
cacheable = False
else:
cacheable = True
if successes_cache_file and cacheable:
_logging.debug("Getting transitive hash for %s ... " % gtest)
try:
gtest_hash = transitive_hash(gtest)
except:
print "Failed to get transitive hash for %s" % gtest
return 1
_logging.debug(" Transitive hash: %s" % gtest_hash)
if gtest_hash in successes:
print "Skipping %s (previously succeeded)" % gtest
continue
print "Running %s...." % gtest,
sys.stdout.flush()
try:
subprocess.check_output(["./" + gtest], stderr=subprocess.STDOUT)
print "Succeeded"
# Record success.
if successes_cache_filename and cacheable:
successes.add(gtest_hash)
successes_cache_file.write(gtest_hash + '\n')
successes_cache_file.flush()
except subprocess.CalledProcessError as e:
print "Failed with exit code %d and output:" % e.returncode
print 72 * '-'
print e.output
print 72 * '-'
return 1
except OSError as e:
print " Failed to start test"
return 1
print "All tests succeeded"
if successes_cache_file:
successes_cache_file.close()
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv))
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