blob: 799d156d8a24b2a16ca4797819b5bc63acbc6c50 [file] [log] [blame]
Ulf Adamsfd370042017-06-16 15:52:06 +02001// Copyright 2017 The Bazel Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.runtime;
15
16import static com.google.common.truth.Truth.assertThat;
janakrd9e8f582021-06-09 13:37:53 -070017import static org.mockito.Mockito.verify;
Ulf Adamsfd370042017-06-16 15:52:06 +020018
19import com.google.common.collect.ImmutableList;
janakrb2f33ea2019-05-08 10:56:43 -070020import com.google.common.eventbus.EventBus;
21import com.google.devtools.build.lib.analysis.BlazeDirectories;
22import com.google.devtools.build.lib.analysis.ServerDirectories;
janakrb2f33ea2019-05-08 10:56:43 -070023import com.google.devtools.build.lib.exec.BinTools;
24import com.google.devtools.build.lib.runtime.commands.VersionCommand;
mschallerfbc43bb2020-05-20 00:59:41 -070025import com.google.devtools.build.lib.server.FailureDetails.Crash;
26import com.google.devtools.build.lib.server.FailureDetails.Crash.Code;
27import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
janakr86e95382020-04-10 09:00:47 -070028import com.google.devtools.build.lib.util.DetailedExitCode;
janakr97c0bd12020-09-08 13:19:03 -070029import com.google.devtools.build.lib.vfs.DigestHashFunction;
janakrb2f33ea2019-05-08 10:56:43 -070030import com.google.devtools.build.lib.vfs.FileSystem;
janakrb2a94342022-02-05 22:02:14 -080031import com.google.devtools.build.lib.vfs.SyscallCache;
janakrb2f33ea2019-05-08 10:56:43 -070032import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
33import com.google.devtools.common.options.OptionsBase;
34import com.google.devtools.common.options.OptionsParser;
35import com.google.devtools.common.options.OptionsParsingResult;
Googler6ebc9fb2021-02-10 10:10:59 -080036import com.google.protobuf.Any;
37import com.google.protobuf.ByteString;
38import com.google.protobuf.BytesValue;
39import com.google.protobuf.StringValue;
Ulf Adamsfd370042017-06-16 15:52:06 +020040import java.util.Arrays;
janakr8e881f72021-07-07 22:57:33 -070041import java.util.concurrent.atomic.AtomicReference;
Ulf Adamsfd370042017-06-16 15:52:06 +020042import org.junit.Test;
43import org.junit.runner.RunWith;
44import org.junit.runners.JUnit4;
janakrb2f33ea2019-05-08 10:56:43 -070045import org.mockito.Mockito;
Ulf Adamsfd370042017-06-16 15:52:06 +020046
47/** Tests for {@link BlazeRuntime} static methods. */
48@RunWith(JUnit4.class)
49public class BlazeRuntimeTest {
Ulf Adamsfd370042017-06-16 15:52:06 +020050
51 @Test
jhorvitz1e803ab2021-05-06 10:22:28 -070052 public void optionSplitting() {
Ulf Adamsfd370042017-06-16 15:52:06 +020053 BlazeRuntime.CommandLineOptions options =
54 BlazeRuntime.splitStartupOptions(
jhorvitz1e803ab2021-05-06 10:22:28 -070055 ImmutableList.of(),
56 "--install_base=/foo --host_jvm_args=-Xmx1B",
57 "build",
58 "//foo:bar",
59 "--nobuild");
Ulf Adamsfd370042017-06-16 15:52:06 +020060 assertThat(options.getStartupArgs())
61 .isEqualTo(Arrays.asList("--install_base=/foo --host_jvm_args=-Xmx1B"));
62 assertThat(options.getOtherArgs()).isEqualTo(Arrays.asList("build", "//foo:bar", "--nobuild"));
63 }
64
65 // A regression test to make sure that the 'no' prefix is handled correctly.
66 @Test
jhorvitz1e803ab2021-05-06 10:22:28 -070067 public void optionSplittingNoPrefix() {
68 BlazeRuntime.CommandLineOptions options =
69 BlazeRuntime.splitStartupOptions(ImmutableList.of(), "--nobatch", "build");
Ulf Adamsfd370042017-06-16 15:52:06 +020070 assertThat(options.getStartupArgs()).isEqualTo(Arrays.asList("--nobatch"));
71 assertThat(options.getOtherArgs()).isEqualTo(Arrays.asList("build"));
72 }
janakrb2f33ea2019-05-08 10:56:43 -070073
74 private static final ImmutableList<Class<? extends OptionsBase>> COMMAND_ENV_REQUIRED_OPTIONS =
75 ImmutableList.of(CommonCommandOptions.class, ClientOptions.class);
76
77 @Test
78 public void crashTest() throws Exception {
janakr97c0bd12020-09-08 13:19:03 -070079 FileSystem fs = new InMemoryFileSystem(DigestHashFunction.SHA256);
janakrb2f33ea2019-05-08 10:56:43 -070080 ServerDirectories serverDirectories =
81 new ServerDirectories(
82 fs.getPath("/install"), fs.getPath("/output"), fs.getPath("/output_user"));
83 BlazeRuntime runtime =
84 new BlazeRuntime.Builder()
janakrb2f33ea2019-05-08 10:56:43 -070085 .setFileSystem(fs)
janakr8e881f72021-07-07 22:57:33 -070086 .setProductName("foo product")
janakrb2f33ea2019-05-08 10:56:43 -070087 .setServerDirectories(serverDirectories)
88 .setStartupOptionsProvider(Mockito.mock(OptionsParsingResult.class))
89 .build();
janakr8e881f72021-07-07 22:57:33 -070090 AtomicReference<String> shutdownMessage = new AtomicReference<>();
janakrb2f33ea2019-05-08 10:56:43 -070091 BlazeDirectories directories =
92 new BlazeDirectories(
93 serverDirectories, fs.getPath("/workspace"), fs.getPath("/system_javabase"), "blaze");
94 BlazeWorkspace workspace = runtime.initWorkspace(directories, BinTools.empty(directories));
95 EventBus eventBus = Mockito.mock(EventBus.class);
jcater706a22e2019-06-17 09:56:03 -070096 OptionsParser options =
97 OptionsParser.builder().optionsClasses(COMMAND_ENV_REQUIRED_OPTIONS).build();
janakrd9e8f582021-06-09 13:37:53 -070098 Thread commandThread = Mockito.mock(Thread.class);
janakrb2f33ea2019-05-08 10:56:43 -070099 CommandEnvironment env =
100 new CommandEnvironment(
101 runtime,
102 workspace,
103 eventBus,
janakrd9e8f582021-06-09 13:37:53 -0700104 commandThread,
janakrb2f33ea2019-05-08 10:56:43 -0700105 VersionCommand.class.getAnnotation(Command.class),
106 options,
janakrb2a94342022-02-05 22:02:14 -0800107 SyscallCache.NO_CACHE,
janakr45b568b2020-05-13 12:39:27 -0700108 ImmutableList.of(),
109 0L,
jhorvitz4182af42020-12-28 09:57:34 -0800110 0L,
janakr8e881f72021-07-07 22:57:33 -0700111 ImmutableList.of(),
112 shutdownMessage::set);
janakrb2f33ea2019-05-08 10:56:43 -0700113 runtime.beforeCommand(env, options.getOptions(CommonCommandOptions.class));
mschallerfbc43bb2020-05-20 00:59:41 -0700114 DetailedExitCode oom =
115 DetailedExitCode.of(
116 FailureDetail.newBuilder()
117 .setCrash(Crash.newBuilder().setCode(Code.CRASH_OOM))
118 .build());
119 runtime.cleanUpForCrash(oom);
120 BlazeCommandResult mainThreadCrash =
121 BlazeCommandResult.failureDetail(
122 FailureDetail.newBuilder()
123 .setCrash(Crash.newBuilder().setCode(Code.CRASH_UNKNOWN))
124 .build());
125 assertThat(runtime.afterCommand(env, mainThreadCrash).getDetailedExitCode()).isEqualTo(oom);
janakrd9e8f582021-06-09 13:37:53 -0700126 // Confirm that runtime interrupted the command thread.
127 verify(commandThread).interrupt();
janakr8e881f72021-07-07 22:57:33 -0700128 assertThat(shutdownMessage.get()).isEqualTo("foo product is crashing: ");
janakrb2f33ea2019-05-08 10:56:43 -0700129 }
michajlo8454a182020-08-25 16:04:27 -0700130
131 @Test
Googler6ebc9fb2021-02-10 10:10:59 -0800132 public void resultExtensions() throws Exception {
133 FileSystem fs = new InMemoryFileSystem(DigestHashFunction.SHA256);
134 ServerDirectories serverDirectories =
135 new ServerDirectories(
136 fs.getPath("/install"), fs.getPath("/output"), fs.getPath("/output_user"));
137 BlazeRuntime runtime =
138 new BlazeRuntime.Builder()
Googler6ebc9fb2021-02-10 10:10:59 -0800139 .setFileSystem(fs)
140 .setProductName("bazel")
141 .setServerDirectories(serverDirectories)
142 .setStartupOptionsProvider(Mockito.mock(OptionsParsingResult.class))
143 .build();
144 BlazeDirectories directories =
145 new BlazeDirectories(
146 serverDirectories, fs.getPath("/workspace"), fs.getPath("/system_javabase"), "blaze");
147 BlazeWorkspace workspace = runtime.initWorkspace(directories, BinTools.empty(directories));
148 CommandEnvironment env =
149 new CommandEnvironment(
150 runtime,
151 workspace,
152 Mockito.mock(EventBus.class),
153 Thread.currentThread(),
154 VersionCommand.class.getAnnotation(Command.class),
155 OptionsParser.builder().optionsClasses(COMMAND_ENV_REQUIRED_OPTIONS).build(),
janakrb2a94342022-02-05 22:02:14 -0800156 SyscallCache.NO_CACHE,
Googler6ebc9fb2021-02-10 10:10:59 -0800157 ImmutableList.of(),
158 0L,
159 0L,
janakr8e881f72021-07-07 22:57:33 -0700160 ImmutableList.of(),
161 s -> {});
Googler6ebc9fb2021-02-10 10:10:59 -0800162 Any anyFoo = Any.pack(StringValue.of("foo"));
163 Any anyBar = Any.pack(BytesValue.of(ByteString.copyFromUtf8("bar")));
164 env.addResponseExtensions(ImmutableList.of(anyFoo, anyBar));
165 assertThat(runtime.afterCommand(env, BlazeCommandResult.success()).getResponseExtensions())
166 .containsExactly(anyFoo, anyBar);
167 }
168
169 @Test
michajlo8454a182020-08-25 16:04:27 -0700170 public void addsCommandsFromModules() throws Exception {
janakr97c0bd12020-09-08 13:19:03 -0700171 FileSystem fs = new InMemoryFileSystem(DigestHashFunction.SHA256);
michajlo8454a182020-08-25 16:04:27 -0700172 ServerDirectories serverDirectories =
173 new ServerDirectories(
174 fs.getPath("/install"), fs.getPath("/output"), fs.getPath("/output_user"));
175 BlazeRuntime runtime =
176 new BlazeRuntime.Builder()
177 .addBlazeModule(new FooCommandModule())
178 .addBlazeModule(new BarCommandModule())
179 .setFileSystem(fs)
180 .setProductName("bazel")
181 .setServerDirectories(serverDirectories)
182 .setStartupOptionsProvider(Mockito.mock(OptionsParsingResult.class))
183 .build();
184
185 assertThat(runtime.getCommandMap().keySet()).containsExactly("foo", "bar").inOrder();
186 assertThat(runtime.getCommandMap().get("foo")).isInstanceOf(FooCommandModule.FooCommand.class);
187 assertThat(runtime.getCommandMap().get("bar")).isInstanceOf(BarCommandModule.BarCommand.class);
188 }
189
190 private static class FooCommandModule extends BlazeModule {
191 @Command(name = "foo", shortDescription = "", help = "")
192 private static class FooCommand implements BlazeCommand {
193
194 @Override
195 public BlazeCommandResult exec(CommandEnvironment env, OptionsParsingResult options) {
196 return null;
197 }
198 }
199
200 @Override
201 public void serverInit(OptionsParsingResult startupOptions, ServerBuilder builder) {
202 builder.addCommands(new FooCommand());
203 }
204 }
205
206 private static class BarCommandModule extends BlazeModule {
207 @Command(name = "bar", shortDescription = "", help = "")
208 private static class BarCommand implements BlazeCommand {
209
210 @Override
211 public BlazeCommandResult exec(CommandEnvironment env, OptionsParsingResult options) {
212 return null;
213 }
214 }
215
216 @Override
217 public void serverInit(OptionsParsingResult startupOptions, ServerBuilder builder) {
218 builder.addCommands(new BarCommand());
219 }
220 }
Ulf Adamsfd370042017-06-16 15:52:06 +0200221}