aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Han-Wen Nienhuys <hanwen@google.com>2015-09-28 10:15:15 +0000
committerGravatar Han-Wen Nienhuys <hanwen@google.com>2015-09-28 11:40:03 +0000
commita51b3f781252b8fe672fdf4545d2eb17e304c2c1 (patch)
tree2d026ceacf838cd5a8042a04aca4049e39be3670 /src
parent22616ae8ea53df3909fd16b74e0d9210138dc2c2 (diff)
RELNOTES: remove webstatusserver (--use_webstatusserver).
It seems unused, and the Bazel dashboard is more useful, as can persist results. -- MOS_MIGRATED_REVID=104085798
Diffstat (limited to 'src')
-rw-r--r--src/main/cpp/blaze.cc4
-rw-r--r--src/main/java/BUILD20
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/BazelMain.java3
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/test/StandaloneTestStrategy.java8
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/test/TestStrategy.java14
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java5
-rw-r--r--src/main/java/com/google/devtools/build/lib/standalone/StandaloneActionContextProvider.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/webstatusserver/IndexPageHandler.java82
-rw-r--r--src/main/java/com/google/devtools/build/lib/webstatusserver/StaticResourceHandler.java81
-rw-r--r--src/main/java/com/google/devtools/build/lib/webstatusserver/TestStatusHandler.java149
-rw-r--r--src/main/java/com/google/devtools/build/lib/webstatusserver/WebStatusBuildLog.java200
-rw-r--r--src/main/java/com/google/devtools/build/lib/webstatusserver/WebStatusEventCollector.java135
-rw-r--r--src/main/java/com/google/devtools/build/lib/webstatusserver/WebStatusServerModule.java161
-rw-r--r--src/main/java/com/google/devtools/build/lib/webstatusserver/static/index.html14
-rw-r--r--src/main/java/com/google/devtools/build/lib/webstatusserver/static/index.js75
-rw-r--r--src/main/java/com/google/devtools/build/lib/webstatusserver/static/style.css39
-rw-r--r--src/main/java/com/google/devtools/build/lib/webstatusserver/static/test.html28
-rw-r--r--src/main/java/com/google/devtools/build/lib/webstatusserver/static/test.js384
18 files changed, 14 insertions, 1394 deletions
diff --git a/src/main/cpp/blaze.cc b/src/main/cpp/blaze.cc
index 641b60c291..bda1384e4f 100644
--- a/src/main/cpp/blaze.cc
+++ b/src/main/cpp/blaze.cc
@@ -340,10 +340,6 @@ static vector<string> GetArgumentArray() {
} else {
result.push_back("--nofatal_event_bus_exceptions");
}
- if (globals->options.webstatus_port) {
- result.push_back("--use_webstatusserver=" + \
- ToString(globals->options.webstatus_port));
- }
// This is only for Blaze reporting purposes; the real interpretation of the
// jvm flags occurs when we set up the java command line.
diff --git a/src/main/java/BUILD b/src/main/java/BUILD
index 0748fcc761..84cbf0b81e 100644
--- a/src/main/java/BUILD
+++ b/src/main/java/BUILD
@@ -524,25 +524,6 @@ java_library(
)
java_library(
- name = "webstatusserver",
- srcs = glob([
- "com/google/devtools/build/lib/webstatusserver/**/*.java",
- ]),
- deps = [
- ":analysis-exec-rules-skyframe",
- ":buildtool-runtime",
- ":clock",
- ":events",
- ":options",
- ":packages",
- ":util",
- "//src/main/protobuf:proto_test_status",
- "//third_party:gson",
- "//third_party:guava",
- ],
-)
-
-java_library(
name = "bazel-core",
srcs = glob(
[
@@ -601,7 +582,6 @@ java_library(
":unix",
":util",
":vfs",
- ":webstatusserver",
"//src/java_tools/singlejar:zip",
"//src/main/java/com/google/devtools/build/lib/bazel/dash",
"//src/main/java/com/google/devtools/build/lib/sandbox",
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/BazelMain.java b/src/main/java/com/google/devtools/build/lib/bazel/BazelMain.java
index 6aea6e4508..2b29f2dc2f 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/BazelMain.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/BazelMain.java
@@ -48,8 +48,7 @@ public final class BazelMain {
com.google.devtools.build.lib.worker.WorkerModule.class,
com.google.devtools.build.lib.standalone.StandaloneModule.class,
com.google.devtools.build.lib.sandbox.SandboxModule.class,
- com.google.devtools.build.lib.runtime.BuildSummaryStatsModule.class,
- com.google.devtools.build.lib.webstatusserver.WebStatusServerModule.class);
+ com.google.devtools.build.lib.runtime.BuildSummaryStatsModule.class);
public static void main(String[] args) {
BlazeVersionInfo.setBuildInfo(tryGetBuildInfo());
diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/StandaloneTestStrategy.java b/src/main/java/com/google/devtools/build/lib/rules/test/StandaloneTestStrategy.java
index 1d1e101b18..eb1fde55e0 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/test/StandaloneTestStrategy.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/test/StandaloneTestStrategy.java
@@ -54,10 +54,12 @@ public class StandaloneTestStrategy extends TestStrategy {
private final Path workspace;
- public StandaloneTestStrategy(OptionsClassProvider requestOptions,
- OptionsClassProvider startupOptions, BinTools binTools, Map<String, String> clientEnv,
+ public StandaloneTestStrategy(
+ OptionsClassProvider requestOptions,
+ BinTools binTools,
+ Map<String, String> clientEnv,
Path workspace) {
- super(requestOptions, startupOptions, binTools, clientEnv);
+ super(requestOptions, binTools, clientEnv);
this.workspace = workspace;
}
diff --git a/src/main/java/com/google/devtools/build/lib/rules/test/TestStrategy.java b/src/main/java/com/google/devtools/build/lib/rules/test/TestStrategy.java
index cc2c43b2c2..329e995ce4 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/test/TestStrategy.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/test/TestStrategy.java
@@ -29,7 +29,6 @@ import com.google.devtools.build.lib.exec.ExecutionOptions;
import com.google.devtools.build.lib.exec.SymlinkTreeHelper;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.profiler.ProfilerTask;
-import com.google.devtools.build.lib.runtime.BlazeServerStartupOptions;
import com.google.devtools.build.lib.util.ShellEscaper;
import com.google.devtools.build.lib.util.io.FileWatcher;
import com.google.devtools.build.lib.util.io.OutErr;
@@ -129,20 +128,17 @@ public abstract class TestStrategy implements TestActionContext {
// Used for generating unique temporary directory names.
private final AtomicInteger tmpIndex = new AtomicInteger(0);
- private final boolean statusServerRunning;
protected final ImmutableMap<String, String> clientEnv;
protected final ExecutionOptions executionOptions;
protected final BinTools binTools;
- public TestStrategy(OptionsClassProvider requestOptionsProvider,
- OptionsClassProvider startupOptionsProvider, BinTools binTools,
+ public TestStrategy(
+ OptionsClassProvider requestOptionsProvider,
+ BinTools binTools,
Map<String, String> clientEnv) {
this.executionOptions = requestOptionsProvider.getOptions(ExecutionOptions.class);
this.binTools = binTools;
this.clientEnv = ImmutableMap.copyOf(clientEnv);
- BlazeServerStartupOptions startupOptions =
- startupOptionsProvider.getOptions(BlazeServerStartupOptions.class);
- statusServerRunning = startupOptions != null && startupOptions.useWebStatusServer > 0;
}
@Override
@@ -315,8 +311,8 @@ public abstract class TestStrategy implements TestActionContext {
@Nullable
protected TestCase parseTestResult(Path resultFile) {
/* xml files. We avoid parsing it unnecessarily, since test results can potentially consume
- a large amount of memory. */
- if (executionOptions.testSummary != TestSummaryFormat.DETAILED && !statusServerRunning) {
+ a large amount of memory. */
+ if (executionOptions.testSummary != TestSummaryFormat.DETAILED) {
return null;
}
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java
index 1e82d8fc9f..244cb709f7 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java
@@ -235,9 +235,4 @@ public class BlazeServerStartupOptions extends OptionsBase {
+ "changes instead of scanning every file for a change.")
public boolean watchFS;
- @Option(name = "use_webstatusserver",
- defaultValue = "0",
- category = "server startup",
- help = "Specifies port to run web status server on (0 to disable, which is default).")
- public int useWebStatusServer;
}
diff --git a/src/main/java/com/google/devtools/build/lib/standalone/StandaloneActionContextProvider.java b/src/main/java/com/google/devtools/build/lib/standalone/StandaloneActionContextProvider.java
index 430f2666b8..b1d2fa682d 100644
--- a/src/main/java/com/google/devtools/build/lib/standalone/StandaloneActionContextProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/standalone/StandaloneActionContextProvider.java
@@ -69,9 +69,9 @@ public class StandaloneActionContextProvider extends ActionContextProvider {
BlazeRuntime runtime = env.getRuntime();
boolean verboseFailures = buildRequest.getOptions(ExecutionOptions.class).verboseFailures;
- TestActionContext testStrategy = new StandaloneTestStrategy(buildRequest,
- runtime.getStartupOptionsProvider(), runtime.getBinTools(), env.getClientEnv(),
- runtime.getWorkspace());
+ TestActionContext testStrategy =
+ new StandaloneTestStrategy(
+ buildRequest, runtime.getBinTools(), env.getClientEnv(), runtime.getWorkspace());
Builder<ActionContext> strategiesBuilder = ImmutableList.builder();
diff --git a/src/main/java/com/google/devtools/build/lib/webstatusserver/IndexPageHandler.java b/src/main/java/com/google/devtools/build/lib/webstatusserver/IndexPageHandler.java
deleted file mode 100644
index 757fa954f2..0000000000
--- a/src/main/java/com/google/devtools/build/lib/webstatusserver/IndexPageHandler.java
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2014 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.devtools.build.lib.webstatusserver;
-
-import com.google.common.collect.ImmutableList;
-import com.google.gson.Gson;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonObject;
-
-import com.sun.net.httpserver.HttpExchange;
-import com.sun.net.httpserver.HttpHandler;
-import com.sun.net.httpserver.HttpServer;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Handlers for displaying the index page of server.
- *
- */
-public class IndexPageHandler {
- private List<TestStatusHandler> testHandlers = new ArrayList<>();
- private IndexPageJsonData dataHandler;
- private StaticResourceHandler frontendHandler;
-
- public IndexPageHandler(HttpServer server, List<TestStatusHandler> testHandlers) {
- this.testHandlers = testHandlers;
- this.dataHandler = new IndexPageJsonData(this);
- this.frontendHandler =
- StaticResourceHandler.createFromRelativePath("static/index.html", "text/html");
- server.createContext("/", frontendHandler);
- server.createContext("/tests/list", dataHandler);
- }
-
- /**
- * Puts data from the build log into json suitable for frontend.
- *
- */
- private class IndexPageJsonData implements HttpHandler {
- private IndexPageHandler pageHandler;
- private Gson gson = new Gson();
- public IndexPageJsonData(IndexPageHandler indexPageHandler) {
- this.pageHandler = indexPageHandler;
- }
-
- @Override
- public void handle(HttpExchange exchange) throws IOException {
- exchange.getResponseHeaders().put("Content-Type", ImmutableList.of("application/json"));
- JsonArray response = new JsonArray();
- for (TestStatusHandler handler : this.pageHandler.testHandlers) {
- WebStatusBuildLog buildLog = handler.getBuildLog();
- JsonObject test = new JsonObject();
- test.add("targets", gson.toJsonTree(buildLog.getTargetList()));
- test.addProperty("startTime", buildLog.getStartTime());
- test.addProperty("finished", buildLog.finished());
- test.addProperty("uuid", buildLog.getCommandId().toString());
- response.add(test);
- }
- String serializedResponse = response.toString();
- exchange.sendResponseHeaders(200, serializedResponse.length());
- try (OutputStream os = exchange.getResponseBody()) {
- os.write(serializedResponse.getBytes(StandardCharsets.UTF_8));
- }
- }
- }
-}
-
diff --git a/src/main/java/com/google/devtools/build/lib/webstatusserver/StaticResourceHandler.java b/src/main/java/com/google/devtools/build/lib/webstatusserver/StaticResourceHandler.java
deleted file mode 100644
index 65d12f6702..0000000000
--- a/src/main/java/com/google/devtools/build/lib/webstatusserver/StaticResourceHandler.java
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2014 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.devtools.build.lib.webstatusserver;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.io.CharStreams;
-import com.google.devtools.build.lib.util.ResourceFileLoader;
-
-import com.sun.net.httpserver.HttpExchange;
-import com.sun.net.httpserver.HttpHandler;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-
-/**
- * Handler for static resources (JS, html, css...)
- */
-public class StaticResourceHandler implements HttpHandler {
- private String response;
- private List<String> contentType;
- private int httpCode;
-
- public static StaticResourceHandler createFromAbsolutePath(String path, String contentType) {
- return new StaticResourceHandler(path, contentType, true);
- }
-
- public static StaticResourceHandler createFromRelativePath(String path, String contentType) {
- return new StaticResourceHandler(path, contentType, false);
- }
-
- private StaticResourceHandler(String path, String contentType, boolean absolutePath) {
- try {
- if (absolutePath) {
- InputStream resourceStream = loadFromAbsolutePath(WebStatusServerModule.class, path);
- response = CharStreams.toString(new InputStreamReader(resourceStream));
-
- } else {
- response = ResourceFileLoader.loadResource(WebStatusServerModule.class, path);
- }
- httpCode = 200;
- } catch (IOException e) {
- throw new IllegalArgumentException("resource " + path + " not found");
- }
- this.contentType = ImmutableList.of(contentType);
- }
-
- @Override
- public void handle(HttpExchange exchange) throws IOException {
- exchange.getResponseHeaders().put("Content-Type", contentType);
- exchange.sendResponseHeaders(httpCode, response.length());
- try (OutputStream os = exchange.getResponseBody()) {
- os.write(response.getBytes(StandardCharsets.UTF_8));
- }
- }
-
- public static InputStream loadFromAbsolutePath(Class<?> loadingClass, String path)
- throws IOException {
- URL resourceUrl = loadingClass.getClassLoader().getResource(path);
- if (resourceUrl == null) {
- throw new IllegalArgumentException("resource " + path + " not found");
- }
- return resourceUrl.openStream();
- }
-}
diff --git a/src/main/java/com/google/devtools/build/lib/webstatusserver/TestStatusHandler.java b/src/main/java/com/google/devtools/build/lib/webstatusserver/TestStatusHandler.java
deleted file mode 100644
index 149a310a28..0000000000
--- a/src/main/java/com/google/devtools/build/lib/webstatusserver/TestStatusHandler.java
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2014 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.devtools.build.lib.webstatusserver;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableList.Builder;
-import com.google.gson.Gson;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.reflect.TypeToken;
-
-import com.sun.net.httpserver.HttpContext;
-import com.sun.net.httpserver.HttpExchange;
-import com.sun.net.httpserver.HttpHandler;
-import com.sun.net.httpserver.HttpServer;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.lang.reflect.Type;
-import java.nio.charset.StandardCharsets;
-import java.util.Map;
-import java.util.Map.Entry;
-
-/**
- * Collection of handlers for displaying the test data.
- */
-class TestStatusHandler {
- private StaticResourceHandler frontendHandler;
- private WebStatusBuildLog buildLog;
- private HttpHandler detailsHandler;
- private HttpServer server;
- private ImmutableList<HttpContext> contexts;
- private CommandJsonData commandHandler;
- private Gson gson = new Gson();
-
- public TestStatusHandler(HttpServer server, WebStatusBuildLog buildLog) {
- Builder<HttpContext> builder = ImmutableList.builder();
- this.buildLog = buildLog;
- this.server = server;
- detailsHandler = new TestStatusResultJsonData(this);
- commandHandler = new CommandJsonData(this);
- frontendHandler = StaticResourceHandler.createFromRelativePath("static/test.html", "text/html");
- builder.add(
- server.createContext("/tests/" + buildLog.getCommandId() + "/details", detailsHandler));
- builder.add(
- server.createContext("/tests/" + buildLog.getCommandId() + "/info", commandHandler));
- builder.add(server.createContext("/tests/" + buildLog.getCommandId(), frontendHandler));
- contexts = builder.build();
- }
-
- public WebStatusBuildLog getBuildLog() {
- return buildLog;
- }
-
-
- /**
- * Serves JSON objects containing command info, which will be rendered by frontend.
- */
- private class CommandJsonData implements HttpHandler {
- private TestStatusHandler testStatusHandler;
-
- public CommandJsonData(TestStatusHandler testStatusHandler) {
- this.testStatusHandler = testStatusHandler;
- }
-
- @Override
- public void handle(HttpExchange exchange) throws IOException {
- exchange.getResponseHeaders().put("Content-Type", ImmutableList.of("application/json"));
- Type commandInfoType = new TypeToken<Map<String, JsonElement>>() {}.getType();
- JsonObject response = gson.toJsonTree(testStatusHandler.buildLog.getCommandInfo(),
- commandInfoType).getAsJsonObject();
- response.addProperty("startTime", testStatusHandler.buildLog.getStartTime());
- response.addProperty("finished", testStatusHandler.buildLog.finished());
-
- String serializedResponse = response.toString();
- exchange.sendResponseHeaders(200, serializedResponse.length());
- try (OutputStream os = exchange.getResponseBody()) {
- os.write(serializedResponse.getBytes(StandardCharsets.UTF_8));
- }
- }
- }
-
- /**
- * Serves JSON objects containing test cases, which will be rendered by frontend.
- */
- private class TestStatusResultJsonData implements HttpHandler {
- private TestStatusHandler testStatusHandler;
-
- public TestStatusResultJsonData(TestStatusHandler testStatusHandler) {
- this.testStatusHandler = testStatusHandler;
- }
-
- @Override
- public void handle(HttpExchange exchange) throws IOException {
- Map<String, JsonObject> testInfo = testStatusHandler.buildLog.getTestCases();
- exchange.getResponseHeaders().put("Content-Type", ImmutableList.of("application/json"));
- JsonObject response = new JsonObject();
- for (Entry<String, JsonObject> testCase : testInfo.entrySet()) {
- response.add(testCase.getKey(), testCase.getValue());
- }
-
- String serializedResponse = response.toString();
- exchange.sendResponseHeaders(200, serializedResponse.length());
- try (OutputStream os = exchange.getResponseBody()) {
- os.write(serializedResponse.getBytes(StandardCharsets.UTF_8));
- }
- }
- }
-
- /**
- * Adds another URI for existing test data. If specified URI is already used by some other
- * handler, the previous handler will be removed.
- */
- public void overrideURI(String uri) {
- String detailsPath = uri + "/details";
- String commandPath = uri + "/info";
- try {
- this.server.removeContext(detailsPath);
- this.server.removeContext(commandPath);
- } catch (IllegalArgumentException e) {
- // There was nothing to remove, so proceed with creation (unfortunately the server api doesn't
- // have "hasContext" method)
- }
- this.server.createContext(detailsPath, this.detailsHandler);
- this.server.createContext(commandPath, this.commandHandler);
- }
-
- /**
- * Deregisters all the handlers associated with the test.
- */
- public void deregister() {
- for (HttpContext c : this.contexts) {
- this.server.removeContext(c);
- }
- }
-}
-
diff --git a/src/main/java/com/google/devtools/build/lib/webstatusserver/WebStatusBuildLog.java b/src/main/java/com/google/devtools/build/lib/webstatusserver/WebStatusBuildLog.java
deleted file mode 100644
index 3f483a626a..0000000000
--- a/src/main/java/com/google/devtools/build/lib/webstatusserver/WebStatusBuildLog.java
+++ /dev/null
@@ -1,200 +0,0 @@
-// Copyright 2014 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.devtools.build.lib.webstatusserver;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.devtools.build.lib.cmdline.Label;
-import com.google.devtools.build.lib.view.test.TestStatus.BlazeTestStatus;
-import com.google.devtools.build.lib.view.test.TestStatus.TestCase;
-import com.google.gson.Gson;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.logging.Logger;
-
-/**
- * Stores information about one build command. The data is stored in JSON so that it can be
- * can be easily fed to frontend.
- *
- * <p> The information is grouped into following structures:
- * <ul>
- * <li> {@link #commandInfo} contain information about the build known when it starts but before
- * anything is actually compiled/run
- * <li> {@link #testCases} contain detailed information about each test case ran, for now they're
- *
- * </ul>
- */
-public class WebStatusBuildLog {
- private Gson gson = new Gson();
- private boolean complete = false;
- private static final Logger LOG =
- Logger.getLogger(WebStatusEventCollector.class.getCanonicalName());
- private Map<String, JsonElement> commandInfo = new HashMap<>();
- private Map<String, JsonObject> testCases = new HashMap<>();
- private long startTime;
- private ImmutableList<String> targetList;
- private UUID commandId;
-
- public WebStatusBuildLog(UUID commandId) {
- this.commandId = commandId;
- }
-
- public WebStatusBuildLog addInfo(String key, Object value) {
- commandInfo.put(key, gson.toJsonTree(value));
- return this;
- }
-
- public void addStartTime(long startTime) {
- this.startTime = startTime;
- }
-
- public void addTargetList(List<String> targets) {
- this.targetList = ImmutableList.copyOf(targets);
- }
-
- public void finish() {
- commandInfo = ImmutableMap.copyOf(commandInfo);
- complete = true;
- }
-
- public Map<String, JsonElement> getCommandInfo() {
- return commandInfo;
- }
-
- public ImmutableMap<String, JsonObject> getTestCases() {
- // TODO(bazel-team): not really immutable, since one can do addProperty on
- // values (unfortunately gson doesn't support immutable JsonObjects)
- return ImmutableMap.copyOf(testCases);
- }
-
- public boolean finished() {
- return complete;
- }
-
- public List<String> getTargetList() {
- return targetList;
- }
-
- public long getStartTime() {
- return startTime;
- }
-
- public void addTestTarget(Label label) {
- String targetName = label.toShorthandString();
- if (!testCases.containsKey(targetName)) {
- JsonObject summary = createTestCaseEmptyJsonNode(targetName);
- summary.addProperty("finished", false);
- summary.addProperty("status", "started");
- testCases.put(targetName, summary);
- } else {
- // TODO(bazel-team): figure out if there are any situations it can happen
- }
- }
-
- public void addTestSummary(Label label, BlazeTestStatus status, List<Long> testTimes,
- boolean isCached) {
- JsonObject testCase = testCases.get(label.toShorthandString());
- testCase.addProperty("status", status.toString());
- testCase.add("times", gson.toJsonTree(testTimes));
- testCase.addProperty("cached", isCached);
- testCase.addProperty("finished", true);
- }
-
- public void addTargetBuilt(Label label, boolean success) {
- if (testCases.containsKey(label.toShorthandString())) {
- if (success) {
- testCases.get(label.toShorthandString()).addProperty("status", "built");
- } else {
- testCases.get(label.toShorthandString()).addProperty("status", "build failure");
- }
- } else {
- LOG.info("Unhandled target: " + label);
- }
- }
-
- @VisibleForTesting
- static JsonObject createTestCaseEmptyJsonNode(String fullName) {
- JsonObject currentNode = new JsonObject();
- currentNode.addProperty("fullName", fullName);
- currentNode.addProperty("name", "");
- currentNode.addProperty("className", "");
- currentNode.add("results", new JsonObject());
- currentNode.add("times", new JsonObject());
- currentNode.add("children", new JsonObject());
- currentNode.add("failures", new JsonObject());
- currentNode.add("errors", new JsonObject());
- return currentNode;
- }
-
- private static JsonObject createTestCaseEmptyJsonNode(String fullName, TestCase testCase) {
- JsonObject currentNode = createTestCaseEmptyJsonNode(fullName);
- currentNode.addProperty("name", testCase.getName());
- currentNode.addProperty("className", testCase.getClassName());
- return currentNode;
- }
-
- private JsonObject mergeTestCases(JsonObject currentNode, String fullName, TestCase testCase,
- int shardNumber) {
- if (currentNode == null) {
- currentNode = createTestCaseEmptyJsonNode(fullName, testCase);
- }
-
- if (testCase.getRun()) {
- JsonObject results = (JsonObject) currentNode.get("results");
- JsonObject times = (JsonObject) currentNode.get("times");
-
- if (testCase.hasResult()) {
- results.addProperty(Integer.toString(shardNumber), testCase.getResult());
- }
-
- if (testCase.hasStatus()) {
- results.addProperty(Integer.toString(shardNumber), testCase.getStatus().toString());
- }
-
- if (testCase.hasRunDurationMillis()) {
- times.addProperty(Integer.toString(shardNumber), testCase.getRunDurationMillis());
- }
- }
- JsonObject children = (JsonObject) currentNode.get("children");
-
- for (TestCase child : testCase.getChildList()) {
- String fullChildName = child.getClassName() + "." + child.getName();
- JsonObject childNode = mergeTestCases((JsonObject) children.get(fullChildName), fullChildName,
- child, shardNumber);
- if (!children.has(fullChildName)) {
- children.add(fullChildName, childNode);
- }
- }
- return currentNode;
- }
-
- public void addTestResult(Label label, TestCase testCase, int shardNumber) {
- String testResultFullName = label.toShorthandString();
- if (!testCases.containsKey(testResultFullName)) {
- testCases.put(testResultFullName, createTestCaseEmptyJsonNode(testResultFullName, testCase));
- }
- mergeTestCases(testCases.get(testResultFullName), testResultFullName, testCase, shardNumber);
- }
-
- public UUID getCommandId() {
- return commandId;
- }
-}
diff --git a/src/main/java/com/google/devtools/build/lib/webstatusserver/WebStatusEventCollector.java b/src/main/java/com/google/devtools/build/lib/webstatusserver/WebStatusEventCollector.java
deleted file mode 100644
index b3c3b06d1f..0000000000
--- a/src/main/java/com/google/devtools/build/lib/webstatusserver/WebStatusEventCollector.java
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright 2014 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.devtools.build.lib.webstatusserver;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableList.Builder;
-import com.google.common.eventbus.EventBus;
-import com.google.common.eventbus.Subscribe;
-import com.google.devtools.build.lib.analysis.BlazeVersionInfo;
-import com.google.devtools.build.lib.analysis.ConfiguredTarget;
-import com.google.devtools.build.lib.analysis.TargetCompleteEvent;
-import com.google.devtools.build.lib.buildtool.BuildRequest;
-import com.google.devtools.build.lib.buildtool.buildevent.BuildStartingEvent;
-import com.google.devtools.build.lib.buildtool.buildevent.TestFilteringCompleteEvent;
-import com.google.devtools.build.lib.cmdline.Label;
-import com.google.devtools.build.lib.events.Event;
-import com.google.devtools.build.lib.events.Reporter;
-import com.google.devtools.build.lib.rules.test.TestResult;
-import com.google.devtools.build.lib.runtime.CommandCompleteEvent;
-import com.google.devtools.build.lib.runtime.CommandStartEvent;
-import com.google.devtools.build.lib.runtime.TestSummary;
-
-import java.util.logging.Logger;
-
-/**
- * This class monitors the build progress, collects events and preprocesses them for use by
- * frontend.
- *
- */
-public class WebStatusEventCollector {
- private static final Logger LOG =
- Logger.getLogger(WebStatusEventCollector.class.getCanonicalName());
- private final EventBus eventBus;
- private final Reporter reporter;
- private final int port;
- private WebStatusBuildLog currentBuild;
- private WebStatusServerModule serverModule;
-
- public WebStatusEventCollector(EventBus eventBus, Reporter reporter,
- WebStatusServerModule webStatusServerModule) {
- this.eventBus = eventBus;
- this.eventBus.register(this);
- this.reporter = reporter;
- this.port = webStatusServerModule.getPort();
- this.serverModule = webStatusServerModule;
- LOG.info("Created new status collector");
- }
-
- @Subscribe
- public void buildStarted(BuildStartingEvent startingEvent) {
- BuildRequest request = startingEvent.getRequest();
- BlazeVersionInfo versionInfo = BlazeVersionInfo.instance();
- currentBuild.addStartTime(request.getStartTime());
- currentBuild.addTargetList(request.getTargets());
- currentBuild
- .addInfo("version", versionInfo)
- .addInfo("commandName", request.getCommandName())
- .addInfo("outputFs", startingEvent.getOutputFileSystem())
- .addInfo("symlinkPrefix", request.getSymlinkPrefix())
- .addInfo("optionsDescription", request.getOptionsDescription())
- .addInfo("targets", request.getTargets())
- .addInfo("viewOptions", request.getViewOptions());
- }
-
- @Subscribe
- @SuppressWarnings("unused")
- public void commandComplete(CommandCompleteEvent completeEvent) {
- currentBuild.addInfo("endTime", completeEvent.getEventTimeInEpochTime());
- currentBuild.finish();
- }
-
- @Subscribe
- @SuppressWarnings("unused")
- public void commandStarted(CommandStartEvent event) {
- this.currentBuild = new WebStatusBuildLog(event.getCommandId());
- this.serverModule.commandStarted();
- String webStatusServerUrl = "http://localhost:" + port;
- this.reporter.handle(Event.info("Status page: " + webStatusServerUrl + "/tests/"
- + this.currentBuild.getCommandId() + " (alternative link: " + webStatusServerUrl
- + WebStatusServerModule.LAST_TEST_URI + " )"));
- }
-
- @Subscribe
- public void doneTestFiltering(TestFilteringCompleteEvent event) {
- if (event.getTestTargets() != null) {
- Builder<Label> builder = ImmutableList.builder();
- for (ConfiguredTarget target : event.getTestTargets()) {
- builder.add(target.getLabel());
- }
- doneTestFiltering(builder.build());
- }
- }
-
- @VisibleForTesting
- public void doneTestFiltering(Iterable<Label> testLabels) {
- for (Label label : testLabels) {
- currentBuild.addTestTarget(label);
- }
- }
-
- @Subscribe
- public void testTargetComplete(TestSummary summary) {
- currentBuild.addTestSummary(summary.getTarget().getLabel(), summary.getStatus(),
- summary.getTestTimes(), summary.isCached());
- }
-
- @Subscribe
- public void testTargetResult(TestResult result) {
- currentBuild.addTestResult(result.getTestAction().getOwner().getLabel(),
- result.getData().getTestCase(), result.getShardNum());
- }
-
- @Subscribe
- public void targetComplete(TargetCompleteEvent event) {
- // TODO(bazel-team): would getting more details about failure be useful?
- currentBuild.addTargetBuilt(event.getTarget().getTarget().getLabel(), !event.failed());
- }
-
- public WebStatusBuildLog getBuildLog() {
- return this.currentBuild;
- }
-}
diff --git a/src/main/java/com/google/devtools/build/lib/webstatusserver/WebStatusServerModule.java b/src/main/java/com/google/devtools/build/lib/webstatusserver/WebStatusServerModule.java
deleted file mode 100644
index d8189d38e1..0000000000
--- a/src/main/java/com/google/devtools/build/lib/webstatusserver/WebStatusServerModule.java
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2014 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.devtools.build.lib.webstatusserver;
-
-import com.google.common.collect.ImmutableList;
-import com.google.devtools.build.lib.analysis.BlazeDirectories;
-import com.google.devtools.build.lib.analysis.BlazeVersionInfo;
-import com.google.devtools.build.lib.runtime.BlazeModule;
-import com.google.devtools.build.lib.runtime.BlazeServerStartupOptions;
-import com.google.devtools.build.lib.runtime.Command;
-import com.google.devtools.build.lib.runtime.CommandEnvironment;
-import com.google.devtools.build.lib.util.AbruptExitException;
-import com.google.devtools.build.lib.util.Clock;
-import com.google.devtools.common.options.OptionsBase;
-import com.google.devtools.common.options.OptionsProvider;
-
-import com.sun.net.httpserver.HttpExchange;
-import com.sun.net.httpserver.HttpHandler;
-import com.sun.net.httpserver.HttpServer;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.InetSocketAddress;
-import java.nio.charset.StandardCharsets;
-import java.util.LinkedList;
-import java.util.UUID;
-import java.util.logging.Logger;
-
-/**
- * Web server for monitoring blaze commands status.
- */
-public class WebStatusServerModule extends BlazeModule {
- static final String LAST_TEST_URI = "/tests/last";
- // 100 is an arbitrary limit; it seems like a reasonable size for history and it's okay to change
- // it
- private static final int MAX_TESTS_STORED = 100;
-
- private HttpServer server;
- private boolean running = false;
- private BlazeServerStartupOptions serverOptions;
- private static final Logger LOG =
- Logger.getLogger(WebStatusServerModule.class.getCanonicalName());
- private int port;
- private LinkedList<TestStatusHandler> testsRan = new LinkedList<>();
- @SuppressWarnings("unused")
- private WebStatusEventCollector collector;
- @SuppressWarnings("unused")
- private IndexPageHandler indexHandler;
-
- @Override
- public Iterable<Class<? extends OptionsBase>> getStartupOptions() {
- return ImmutableList.<Class<? extends OptionsBase>>of(BlazeServerStartupOptions.class);
- }
-
- @Override
- public void blazeStartup(OptionsProvider startupOptions, BlazeVersionInfo versionInfo,
- UUID instanceId, BlazeDirectories directories, Clock clock) throws AbruptExitException {
- serverOptions = startupOptions.getOptions(BlazeServerStartupOptions.class);
- if (serverOptions.useWebStatusServer <= 0) {
- LOG.info("web status server disabled");
- return;
- }
- port = serverOptions.useWebStatusServer;
- try {
- server = HttpServer.create(new InetSocketAddress(port), 0);
- serveStaticContent();
- TextHandler lastCommandHandler = new TextHandler("No commands ran yet.");
- server.createContext("/last", lastCommandHandler);
- server.setExecutor(null);
- server.start();
- indexHandler = new IndexPageHandler(server, this.testsRan);
- running = true;
- LOG.info("Running web status server on port " + port);
- } catch (IOException e) {
- // TODO(bazel-team): Display information about why it failed
- running = false;
- LOG.warning("Unable to run web status server on port " + port);
- }
- }
-
- @Override
- public void beforeCommand(Command command, CommandEnvironment env)
- throws AbruptExitException {
- if (!running) {
- return;
- }
- collector =
- new WebStatusEventCollector(env.getEventBus(), env.getReporter(), this);
- }
-
- public void commandStarted() {
- WebStatusBuildLog currentBuild = collector.getBuildLog();
-
- if (testsRan.size() == MAX_TESTS_STORED) {
- TestStatusHandler oldestTest = testsRan.removeLast();
- oldestTest.deregister();
- }
-
- TestStatusHandler lastTest = new TestStatusHandler(server, currentBuild);
- testsRan.add(lastTest);
-
- lastTest.overrideURI(LAST_TEST_URI);
- }
-
- private void serveStaticContent() {
- StaticResourceHandler testjs =
- StaticResourceHandler.createFromRelativePath("static/test.js", "application/javascript");
- StaticResourceHandler indexjs =
- StaticResourceHandler.createFromRelativePath("static/index.js", "application/javascript");
- StaticResourceHandler style =
- StaticResourceHandler.createFromRelativePath("static/style.css", "text/css");
- StaticResourceHandler d3 = StaticResourceHandler.createFromAbsolutePath(
- "third_party/javascript/d3/d3-js.js", "application/javascript");
- StaticResourceHandler jquery = StaticResourceHandler.createFromAbsolutePath(
- "third_party/javascript/jquery/v2_0_3/jquery_uncompressed.jslib",
- "application/javascript");
- StaticResourceHandler testFrontend =
- StaticResourceHandler.createFromRelativePath("static/test.html", "text/html");
-
- server.createContext("/css/style.css", style);
- server.createContext("/js/test.js", testjs);
- server.createContext("/js/index.js", indexjs);
- server.createContext("/js/lib/d3.js", d3);
- server.createContext("/js/lib/jquery.js", jquery);
- server.createContext(LAST_TEST_URI, testFrontend);
- }
-
- private static class TextHandler implements HttpHandler {
- private String response;
-
- private TextHandler(String response) {
- this.response = response;
- }
-
- @Override
- public void handle(HttpExchange exchange) throws IOException {
- exchange.getResponseHeaders().put("Content-Type", ImmutableList.of("text/plain"));
- exchange.sendResponseHeaders(200, response.length());
- try (OutputStream os = exchange.getResponseBody()) {
- os.write(response.getBytes(StandardCharsets.UTF_8));
- }
- }
- }
-
- public int getPort() {
- return port;
- }
-}
-
diff --git a/src/main/java/com/google/devtools/build/lib/webstatusserver/static/index.html b/src/main/java/com/google/devtools/build/lib/webstatusserver/static/index.html
deleted file mode 100644
index f57bc30c8e..0000000000
--- a/src/main/java/com/google/devtools/build/lib/webstatusserver/static/index.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<html>
-<head>
- <title> Bazel web server </title>
- <link rel="stylesheet" type="text/css" href="/css/style.css"></link>
- <script src="/js/lib/d3.js" type="application/javascript"></script>
- <script src="/js/lib/jquery.js" type="application/javascript"></script>
- <script src="/js/index.js" type="application/javascript"></script>
-</head>
-<body onload="showData()">
- <h1> Bazel web server status page </h1>
- <div id="testsList">
- </div>
-</body>
-</html>
diff --git a/src/main/java/com/google/devtools/build/lib/webstatusserver/static/index.js b/src/main/java/com/google/devtools/build/lib/webstatusserver/static/index.js
deleted file mode 100644
index f677b2ff37..0000000000
--- a/src/main/java/com/google/devtools/build/lib/webstatusserver/static/index.js
+++ /dev/null
@@ -1,75 +0,0 @@
-var icons = {
- running: '\u25B6',
- finished: '\u2611'
-};
-
-function showData() {
- renderTestList(getTestsData());
-}
-
-function getTestsData() {
- // TODO(bazel-team): change it to async callback retrieving data in background
- // (for simplicity this is synchronous now)
- return $.ajax({
- type: 'GET',
- url: document.URL + 'tests/list',
- async: false
- }).responseJSON;
-}
-
-function renderTestList(tests) {
- var rows = d3.select('#testsList')
- .selectAll()
- .data(tests)
- .enter().append('div')
- .classed('info-cell', true);
-
- // status
- rows.append('div').classed('info-detail', true).text(function(j) {
- return j.finished ? icons.finished : icons.running;
- });
-
- // target(s) name(s)
- rows.append('div').classed('info-detail', true).text(function(j) {
- if (!j.targets || j.targets.length == 0) {
- return 'Unknown target.';
- } else if (j.targets.length == 1) {
- return j.targets[0];
- }
- return j.targets;
- });
-
- // start time
- rows.append('div').classed('info-detail', true).text(function(j) {
- // Pad value with 2 zeroes
- function pad(value) {
- return value < 10 ? '0' + value : value;
- }
-
- var
- date = new Date(j.startTime),
- today = new Date(Date.now()),
- h = pad(date.getHours()),
- m = pad(date.getMinutes()),
- dd = pad(date.getDay()),
- mm = pad(date.getMonth()),
- yy = date.getYear(),
- day;
-
- // don't show date if ran today
- if (dd != today.getDay() && mm != today.getMonth() &&
- yy != today.getYear()) {
- day = ' on ' + yy + '-' + mm + '-' + dd;
- } else {
- day = '';
- }
- return h + ':' + m;
- });
-
- // link
- rows.append('div').classed('info-detail', true).classed('button', true)
- .append('a').attr('href', function(datum, index) {
- return '/tests/' + datum.uuid;
- })
- .text('link');
-}
diff --git a/src/main/java/com/google/devtools/build/lib/webstatusserver/static/style.css b/src/main/java/com/google/devtools/build/lib/webstatusserver/static/style.css
deleted file mode 100644
index 2ea712d760..0000000000
--- a/src/main/java/com/google/devtools/build/lib/webstatusserver/static/style.css
+++ /dev/null
@@ -1,39 +0,0 @@
-a {
- color: #666
-}
-body {
- font-family: 'Helvetica Neue', HelveticaNeue, Helvetica, sans-serif;
-}
-.test-case {
- outline:1px solid #eeeeee;
- display:block;
- padding:5px
-}
-.test-case:nth-child(odd) {
- background: #eee
-}
-.test-case:nth-child(even) {
- background: #fff
-}
-.test-detail {
- display:inline-block;
- min-width:10px;
- padding-left:5px;
- padding-right:5px
-}
-.info-cell {
- padding:5px;
- background: #eee;
- outline:1px solid #fff;
- display:block
-}
-.info-detail {
- padding-right:5px;
- padding-left:5px;
- display:inline-block
-}
-.button {
- cursor:pointer;
- color:#666;
- float:right
-}
diff --git a/src/main/java/com/google/devtools/build/lib/webstatusserver/static/test.html b/src/main/java/com/google/devtools/build/lib/webstatusserver/static/test.html
deleted file mode 100644
index 04a6fb712c..0000000000
--- a/src/main/java/com/google/devtools/build/lib/webstatusserver/static/test.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<html>
-<head><title>Tests Result Page</title>
- <link rel="stylesheet" type="text/css" href="/css/style.css"></link>
- <script src="/js/lib/d3.js" type="application/javascript"></script>
- <script src="/js/lib/jquery.js" type="application/javascript"></script>
- <script src="/js/test.js" type="application/javascript"></script>
-</head>
-<body>
-<h1> Bazel web status server </h1>
-<div id="testInfo">
- No test info to display.
-</div>
-<br>
-<div id="testFilters">
- <div class="info-cell">
- <input placeholder="Filter by name" type=text id="search"></input>
- <!-- TODO(bazel-team) this is very simplistic view of tests,
- we probably need more filters -->
- <input type=checkbox checked=true id="boxPassed">passed</input>
- <input type=checkbox checked=true id="boxFailed">failed</input>
- <button id="clearFilters"> clear filters </button>
- </div>
-</div>
-<div id="testDetails">
- No test details to display.
-</div>
-</body>
-</html>
diff --git a/src/main/java/com/google/devtools/build/lib/webstatusserver/static/test.js b/src/main/java/com/google/devtools/build/lib/webstatusserver/static/test.js
deleted file mode 100644
index 406dcabd55..0000000000
--- a/src/main/java/com/google/devtools/build/lib/webstatusserver/static/test.js
+++ /dev/null
@@ -1,384 +0,0 @@
-var icons = {
- running: '?',
- passed: '\u2705',
- errors: '\u274c'
-};
-
-
-function showData() {
- renderDetails(getDetailsData(), false);
- renderInfo(getCommandInfo());
-}
-
-function getCommandInfo() {
- var url = document.URL;
- if (url[url.length - 1] != '/') {
- url += '/';
- }
- return $.ajax({
- type: 'GET',
- url: url + 'info',
- async: false
- }).responseJSON;
-}
-
-function getDetailsData() {
- // TODO(bazel-team): auto refresh, async callback
- var url = document.URL;
- if (url[url.length - 1] != '/') {
- url += '/';
- }
- return $.ajax({
- type: 'GET',
- url: url + 'details',
- async: false
- }).responseJSON;
-}
-
-
-function showDate(d) {
- function pad(x) {
- return x < 10 ? '0' + x : '' + x;
- }
- var today = new Date();
- var result = pad(d.getHours()) + ':' + pad(d.getMinutes()) + ':' +
- pad(d.getSeconds());
- if (d.getDate() === today.getDate() && d.getMonth() === today.getMonth() &&
- d.getYear() === today.getYear()) {
- result += ' today';
- } else {
- result += pad(d.getDate()) + ' ' + pad(d.getMonth()) + ' ' + d.getYear();
- }
- return result;
-}
-
-function renderInfo(info) {
- $('#testInfo').empty();
- var data = [
- ['Targets: ', info['targets']],
- ['Started at: ', showDate(new Date(info['startTime']))],
- ];
- if (info['finished']) {
- data.push(['Finished at: ', showDate(new Date(info['endTime']))]);
- } else {
- data.push(['Still running']);
- }
- var selection = d3.select('#testInfo').selectAll()
- .data(data)
- .enter().append('div')
- .classed('info-cell', true);
- selection
- .append('div')
- .classed('info-detail', true)
- .text(function(d) { return d[0]; });
- selection
- .append('div')
- .classed('info-detail', true)
- .text(function(d) { return d[1]; });
-}
-
-// predicate is either a predicate function or null - in the latter case
-// everything is shown
-function renderDetails(tests, predicate) {
- $('#testDetails').empty();
- if (tests.length == 0) {
- $('#testDetails').text('No test details to display.');
- return;
- }
- // flatten object to array and set visibility
- tests = $.map(tests, function(element) {
- if (predicate) {
- setVisibility(predicate, element);
- }
- return element;
- });
- var rows = d3.select('#testDetails').selectAll()
- .data(tests)
- .enter().append('div')
- .classed('test-case', true);
-
- function addTestDetail(selection, toplevel) {
- function fullName() {
- selection.append('div').classed('test-detail', true).text(function(j) {
- return j.fullName;
- });
- }
- function propagateStatus(j) {
- var result = '';
- var failures = [];
- var errors = [];
- $.each(j.results, function(key, value) {
- if (value == 'FAILED') {
- failures.push(key);
- }
- if (value == 'ERROR') {
- errors.push(key);
- }
- });
- if (failures.length > 0) {
- var s = failures.length > 1 ? 's' : '';
- result += 'Failed on ' + failures.length + ' shard' + s + ': ' +
- failures.join();
- }
- if (errors.length > 0) {
- var s = failures.length > 1 ? 's' : '';
- result += 'Errors on ' + errors.length + ' shard' + s + ': ' +
- errors.join();
- }
- if (result == '') {
- return j.status;
- }
- return result;
- }
- function testCaseStatus() {
- selection.append('div')
- .classed('test-detail', true)
- .text(propagateStatus);
- }
- function testTargetStatus() {
- selection.append('div')
- .classed('test-detail', true)
- .text(function(target) {
- var childStatus = propagateStatus(target);
- if (target.finished = false) {
- return target.status + ' ' + stillRunning;
- } else {
- if (childStatus == 'PASSED') {
- return target.status;
- } else {
- return target.status + ' ' + childStatus;
- }
- }
- });
- }
- function testTargetStatusIcon() {
- selection.append('div')
- .classed('test-detail', true)
- .attr('color', function(target) {
- var childStatus = propagateStatus(target);
- if (target.finished == false) {
- return 'running';
- } else {
- if (childStatus == 'PASSED') {
- return 'passed';
- } else {
- return 'errors';
- }
- }})
- .text(function(target) {
- var childStatus = propagateStatus(target);
- if (target.finished == false) {
- return icons.running;
- } else {
- if (childStatus == 'PASSED') {
- return icons.passed;
- } else {
- return icons.errors;
- }
- }
- });
- }
- function testCaseTime() {
- selection.append('div').classed('test-detail', true).text(function(j) {
- var times = $.map(j.times, function(element, key) { return element });
- if (times.length < 1) {
- return '?';
- } else {
- return Math.max.apply(Math, times) / 1000 + ' s';
- }
- });
- }
-
- function visibilityFilter() {
- selection.attr('show', function(datum) {
- return ('show' in datum) ? datum['show'] : true;
- });
- }
-
- // Toplevel nodes represent test targets, so they look a bit different
- if (toplevel) {
- testTargetStatusIcon();
- fullName();
- } else {
- testTargetStatusIcon();
- fullName();
- testCaseStatus();
- testCaseTime();
- }
- visibilityFilter();
- }
-
- function addNestedDetails(table, toplevel) {
- table.sort(function(data1, data2) {
- if (data1.fullName < data2.fullName) {
- return -1;
- }
- if (data1.fullName > data2.fullName) {
- return 1;
- }
- return 0;
- });
-
- addTestDetail(table, toplevel);
-
- // Add children nodes + show/hide button
- var nonLeafNodes = table.filter(function(data, index) {
- return !($.isEmptyObject(data.children));
- });
- var nextLevelNodes = nonLeafNodes.selectAll().data(function(d) {
- return $.map(d.children, function(element, key) { return element });
- });
-
- if (nextLevelNodes.enter().empty()) {
- return;
- }
-
- nonLeafNodes
- .append('div')
- .classed('test-detail', true)
- .classed('button', true)
- .text(function(j) {
- return 'Show details';
- })
- .attr('toggle', 'off')
- .on('click', function(datum) {
- if ($(this).attr('toggle') == 'on') {
- $(this).siblings('.test-case').not('[show=false]').hide();
- $(this).attr('toggle', 'off');
- $(this).text('Show details');
- } else {
- $(this).siblings('.test-case').not('[show=false]').show();
- $(this).attr('toggle', 'on');
- $(this).text('Hide details');
- }
- });
- nextLevelNodes.enter().append('div').classed('test-case', true);
- addNestedDetails(nextLevelNodes, false);
- }
-
- addNestedDetails(rows, true);
- $('.button').siblings('.test-case').hide();
- if (predicate) {
- toggleVisibility();
- }
-}
-
-function toggleVisibility() {
- $('#testDetails > [show=false]').hide();
- $('#testDetails > [show=true]').show();
- $('[toggle=on]').siblings('[show=false]').hide();
- $('[toggle=on]').siblings('[show=true]').show();
-}
-
-function setVisibility(predicate, object) {
- var show = predicate(object);
- var childrenPredicate = predicate;
- // It rarely makes sense to show a non-leaf node and hide its children, so
- // we just show all children
- if (show) {
- childrenPredicate = function() { return true; };
- }
- if ('children' in object) {
- for (var child in object.children) {
- setVisibility(childrenPredicate, object.children[child]);
- show = object.children[child]['show'] || show;
- }
- }
- object['show'] = show;
-}
-
-// given a list of predicates, return a function
-function intersectFilters(filterList) {
- var filters = filterList.filter(function(x) { return x });
- return function(x) {
- for (var i = 0; i < filters.length; i++) {
- if (!filters[i](x)) {
- return false;
- }
- }
- return true;
- }
-}
-
-function textFilterActive() {
- return $('#search').val();
-}
-
-function getTestFilters() {
- var statusFilter = null;
- var textFilter = null;
- var filters = [];
- var passed = $('#boxPassed').prop('checked');
- var failed = $('#boxFailed').prop('checked');
- // add checkbox filters only when necessary (ie. something is unchecked - when
- // everything is checked this means user wants to see everything).
- if (!(passed && failed)) {
- var checkBoxFilters = [];
- if (passed) {
- checkBoxFilters.push(function(object) {
- return object.status == 'PASSED';
- });
- }
- if (failed) {
- checkBoxFilters.push(function(object) {
- return 'status' in object && object.status != 'PASSED';
- });
- }
- filters.push(function(object) {
- return checkBoxFilters.some(function(f) { return f(object); });
- });
- }
- if (textFilterActive()) {
- filters.push(function(object) {
- // TODO(bazel-team): would case insentive search make more sense?
- return ('fullName' in object &&
- object.fullName.indexOf($('#search').val()) != -1);
- });
- }
- return filters;
-}
-
-function redraw() {
- renderDetails(getDetailsData(), intersectFilters(getTestFilters()));
-}
-
-function updateVisibleCases() {
- var predicate = intersectFilters(getTestFilters());
- var parentCases = d3.selectAll('#testDetails > div').data();
- parentCases.forEach(function(element, index) {
- setVisibility(predicate, element);
- });
- d3.selectAll('.test-detail').attr('show', function(datum) {
- return ('show' in datum) ? datum['show'] : true;
- });
- d3.selectAll('.test-case').attr('show', function(datum) {
- return ('show' in datum) ? datum['show'] : true;
- });
- toggleVisibility();
- if (textFilterActive()) {
- // expand nodes to save some clicking - if user searched for something that
- // is leaf of the tree, she definitely wants to see it
- $('#testDetails > [show=true]').find('[toggle=off]').click();
- }
-}
-
-function enableControls() {
- var redrawTimeout = null;
- $('#boxPassed').click(updateVisibleCases);
- $('#boxFailed').click(updateVisibleCases);
- $('#search').keyup(function() {
- clearTimeout(redrawTimeout);
- redrawTimeout = setTimeout(updateVisibleCases, 500);
- });
- $('#clearFilters').click(function() {
- $('#boxPassed').prop('checked', true);
- $('#boxFailed').prop('checked', true);
- $('#search').val('');
- updateVisibleCases();
- });
-}
-
-$(function() {
- showData();
- enableControls();
-});