blob: 53ab069b1b32209a0efa6623a5fd8be62e16b254 [file] [log] [blame]
ulfjack9274cba2017-08-11 23:19:48 +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.exec;
15
16import static com.google.common.truth.Truth.assertThat;
ruperts70d018b2017-09-22 02:20:27 +020017import static org.junit.Assert.fail;
ulfjack9274cba2017-08-11 23:19:48 +020018import static org.mockito.Matchers.any;
19import static org.mockito.Matchers.eq;
20import static org.mockito.Mockito.mock;
21import static org.mockito.Mockito.never;
22import static org.mockito.Mockito.verify;
23import static org.mockito.Mockito.when;
24
25import com.google.devtools.build.lib.actions.ActionExecutionContext;
26import com.google.devtools.build.lib.actions.Spawn;
rupertsda40fbf2017-09-22 05:59:42 +020027import com.google.devtools.build.lib.actions.SpawnResult;
28import com.google.devtools.build.lib.actions.SpawnResult.Status;
ulfjack9274cba2017-08-11 23:19:48 +020029import com.google.devtools.build.lib.exec.SpawnCache.CacheHandle;
ulfjack9274cba2017-08-11 23:19:48 +020030import com.google.devtools.build.lib.exec.SpawnRunner.SpawnExecutionPolicy;
31import com.google.devtools.build.lib.exec.util.SpawnBuilder;
32import com.google.devtools.build.lib.testutil.Suite;
33import com.google.devtools.build.lib.testutil.TestSpec;
34import com.google.devtools.build.lib.vfs.FileSystem;
35import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
36import java.util.Collection;
ruperts940ce202017-09-26 11:47:24 -040037import java.util.Set;
ulfjack9274cba2017-08-11 23:19:48 +020038import org.junit.Before;
39import org.junit.Test;
40import org.junit.runner.RunWith;
41import org.junit.runners.JUnit4;
42import org.mockito.Mock;
43import org.mockito.MockitoAnnotations;
44
45/** Tests for {@link BlazeExecutor}. */
46@RunWith(JUnit4.class)
47@TestSpec(size = Suite.SMALL_TESTS)
48public class AbstractSpawnStrategyTest {
49 private static class TestedSpawnStrategy extends AbstractSpawnStrategy {
50 public TestedSpawnStrategy(SpawnRunner spawnRunner) {
51 super(spawnRunner);
52 }
53 }
54
55 private static final Spawn SIMPLE_SPAWN =
56 new SpawnBuilder("/bin/echo", "Hi!").withEnvironment("VARIABLE", "value").build();
57
58 private final FileSystem fs = new InMemoryFileSystem();
59 @Mock private SpawnRunner spawnRunner;
60 @Mock private ActionExecutionContext actionExecutionContext;
61
62 @Before
63 public final void setUp() throws Exception {
64 MockitoAnnotations.initMocks(this);
65 }
66
67 @Test
68 public void testZeroExit() throws Exception {
69 when(actionExecutionContext.getContext(eq(SpawnCache.class))).thenReturn(SpawnCache.NO_CACHE);
70 when(actionExecutionContext.getExecRoot()).thenReturn(fs.getPath("/execroot"));
ruperts940ce202017-09-26 11:47:24 -040071 SpawnResult spawnResult = new SpawnResult.Builder().setStatus(Status.SUCCESS).build();
ulfjack9274cba2017-08-11 23:19:48 +020072 when(spawnRunner.exec(any(Spawn.class), any(SpawnExecutionPolicy.class)))
ruperts940ce202017-09-26 11:47:24 -040073 .thenReturn(spawnResult);
ulfjack9274cba2017-08-11 23:19:48 +020074
ruperts940ce202017-09-26 11:47:24 -040075 Set<SpawnResult> spawnResults = new TestedSpawnStrategy(spawnRunner)
76 .exec(SIMPLE_SPAWN, actionExecutionContext);
77
78 assertThat(spawnResults).containsExactly(spawnResult);
79
ulfjack9274cba2017-08-11 23:19:48 +020080 // Must only be called exactly once.
81 verify(spawnRunner).exec(any(Spawn.class), any(SpawnExecutionPolicy.class));
82 }
83
84 @Test
85 public void testNonZeroExit() throws Exception {
86 when(actionExecutionContext.getContext(eq(SpawnCache.class))).thenReturn(SpawnCache.NO_CACHE);
87 when(actionExecutionContext.getExecRoot()).thenReturn(fs.getPath("/execroot"));
88 SpawnResult result = new SpawnResult.Builder().setStatus(Status.SUCCESS).setExitCode(1).build();
89 when(spawnRunner.exec(any(Spawn.class), any(SpawnExecutionPolicy.class)))
90 .thenReturn(result);
91
92 try {
ruperts940ce202017-09-26 11:47:24 -040093 // Ignoring the Set<SpawnResult> return value.
ulfjack9274cba2017-08-11 23:19:48 +020094 new TestedSpawnStrategy(spawnRunner).exec(SIMPLE_SPAWN, actionExecutionContext);
ruperts70d018b2017-09-22 02:20:27 +020095 fail("Expected SpawnExecException");
ulfjack9274cba2017-08-11 23:19:48 +020096 } catch (SpawnExecException e) {
97 assertThat(e.getSpawnResult()).isSameAs(result);
98 }
99 // Must only be called exactly once.
100 verify(spawnRunner).exec(any(Spawn.class), any(SpawnExecutionPolicy.class));
101 }
102
103 @Test
104 public void testCacheHit() throws Exception {
105 SpawnCache cache = mock(SpawnCache.class);
ruperts940ce202017-09-26 11:47:24 -0400106 SpawnResult spawnResult = new SpawnResult.Builder().setStatus(Status.SUCCESS).build();
ulfjack9274cba2017-08-11 23:19:48 +0200107 when(cache.lookup(any(Spawn.class), any(SpawnExecutionPolicy.class)))
ruperts940ce202017-09-26 11:47:24 -0400108 .thenReturn(SpawnCache.success(spawnResult));
ulfjack9274cba2017-08-11 23:19:48 +0200109 when(actionExecutionContext.getContext(eq(SpawnCache.class))).thenReturn(cache);
110 when(actionExecutionContext.getExecRoot()).thenReturn(fs.getPath("/execroot"));
111
ruperts940ce202017-09-26 11:47:24 -0400112 Set<SpawnResult> spawnResults = new TestedSpawnStrategy(spawnRunner)
113 .exec(SIMPLE_SPAWN, actionExecutionContext);
114 assertThat(spawnResults).containsExactly(spawnResult);
ulfjack9274cba2017-08-11 23:19:48 +0200115 verify(spawnRunner, never()).exec(any(Spawn.class), any(SpawnExecutionPolicy.class));
116 }
117
118 @SuppressWarnings("unchecked")
119 @Test
120 public void testCacheMiss() throws Exception {
121 SpawnCache cache = mock(SpawnCache.class);
122 CacheHandle entry = mock(CacheHandle.class);
123 when(cache.lookup(any(Spawn.class), any(SpawnExecutionPolicy.class))).thenReturn(entry);
124 when(entry.hasResult()).thenReturn(false);
125 when(entry.willStore()).thenReturn(true);
126
127 when(actionExecutionContext.getContext(eq(SpawnCache.class))).thenReturn(cache);
128 when(actionExecutionContext.getExecRoot()).thenReturn(fs.getPath("/execroot"));
ruperts940ce202017-09-26 11:47:24 -0400129 SpawnResult spawnResult = new SpawnResult.Builder().setStatus(Status.SUCCESS).build();
130 when(spawnRunner.exec(any(Spawn.class), any(SpawnExecutionPolicy.class)))
131 .thenReturn(spawnResult);
ulfjack9274cba2017-08-11 23:19:48 +0200132
ruperts940ce202017-09-26 11:47:24 -0400133 Set<SpawnResult> spawnResults = new TestedSpawnStrategy(spawnRunner)
134 .exec(SIMPLE_SPAWN, actionExecutionContext);
135
136 assertThat(spawnResults).containsExactly(spawnResult);
137
ulfjack9274cba2017-08-11 23:19:48 +0200138 // Must only be called exactly once.
139 verify(spawnRunner).exec(any(Spawn.class), any(SpawnExecutionPolicy.class));
ruperts940ce202017-09-26 11:47:24 -0400140 verify(entry).store(eq(spawnResult), any(Collection.class));
ulfjack9274cba2017-08-11 23:19:48 +0200141 }
142
143 @SuppressWarnings("unchecked")
144 @Test
145 public void testCacheMissWithNonZeroExit() throws Exception {
146 SpawnCache cache = mock(SpawnCache.class);
147 CacheHandle entry = mock(CacheHandle.class);
148 when(cache.lookup(any(Spawn.class), any(SpawnExecutionPolicy.class))).thenReturn(entry);
149 when(entry.hasResult()).thenReturn(false);
150 when(entry.willStore()).thenReturn(true);
151
152 when(actionExecutionContext.getContext(eq(SpawnCache.class))).thenReturn(cache);
153 when(actionExecutionContext.getExecRoot()).thenReturn(fs.getPath("/execroot"));
154 SpawnResult result = new SpawnResult.Builder().setStatus(Status.SUCCESS).setExitCode(1).build();
155 when(spawnRunner.exec(any(Spawn.class), any(SpawnExecutionPolicy.class))).thenReturn(result);
156
157 try {
ruperts940ce202017-09-26 11:47:24 -0400158 // Ignoring the Set<SpawnResult> return value.
ulfjack9274cba2017-08-11 23:19:48 +0200159 new TestedSpawnStrategy(spawnRunner).exec(SIMPLE_SPAWN, actionExecutionContext);
ruperts70d018b2017-09-22 02:20:27 +0200160 fail("Expected SpawnExecException");
ulfjack9274cba2017-08-11 23:19:48 +0200161 } catch (SpawnExecException e) {
162 assertThat(e.getSpawnResult()).isSameAs(result);
163 }
164 // Must only be called exactly once.
165 verify(spawnRunner).exec(any(Spawn.class), any(SpawnExecutionPolicy.class));
166 verify(entry).store(eq(result), any(Collection.class));
167 }
168
169 @Test
170 public void testTagNoCache() throws Exception {
171 SpawnCache cache = mock(SpawnCache.class);
172 when(actionExecutionContext.getContext(eq(SpawnCache.class))).thenReturn(cache);
173 when(actionExecutionContext.getExecRoot()).thenReturn(fs.getPath("/execroot"));
174 when(spawnRunner.exec(any(Spawn.class), any(SpawnExecutionPolicy.class)))
175 .thenReturn(new SpawnResult.Builder().setStatus(Status.SUCCESS).build());
176
177 Spawn uncacheableSpawn =
178 new SpawnBuilder("/bin/echo", "Hi").withExecutionInfo("no-cache", "").build();
ruperts940ce202017-09-26 11:47:24 -0400179
ulfjack9274cba2017-08-11 23:19:48 +0200180 new TestedSpawnStrategy(spawnRunner).exec(uncacheableSpawn, actionExecutionContext);
ruperts940ce202017-09-26 11:47:24 -0400181
ulfjack9274cba2017-08-11 23:19:48 +0200182 // Must only be called exactly once.
183 verify(spawnRunner).exec(any(Spawn.class), any(SpawnExecutionPolicy.class));
184 // Must not be called.
185 verify(cache, never()).lookup(any(Spawn.class), any(SpawnExecutionPolicy.class));
186 }
187}