blob: 8d76c90ecf952e54156137cba0200dca88141ffd [file] [log] [blame]
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +00001// Copyright 2015 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.skyframe;
15
16import static com.google.common.truth.Truth.assertThat;
lberkiaea56b32017-05-30 12:35:33 +020017import static com.google.common.truth.Truth.assertWithMessage;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000018
tomlua155b532017-11-08 20:12:47 +010019import com.google.common.base.Preconditions;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000020import com.google.common.collect.ImmutableList;
21import com.google.common.collect.Maps;
22import com.google.devtools.build.lib.events.util.EventCollectionApparatus;
23import com.google.devtools.build.lib.skyframe.DiffAwarenessManager.ProcessableModifiedFileSet;
24import com.google.devtools.build.lib.vfs.FileSystem;
25import com.google.devtools.build.lib.vfs.ModifiedFileSet;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000026import com.google.devtools.build.lib.vfs.PathFragment;
tomluee6a6862018-01-17 14:36:26 -080027import com.google.devtools.build.lib.vfs.Root;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000028import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
juliexxia618a0762018-08-17 08:33:52 -070029import com.google.devtools.common.options.OptionsProvider;
Ulf Adams2891ec52016-10-13 11:56:18 +000030import java.util.List;
31import java.util.Map;
32import javax.annotation.Nullable;
Han-Wen Nienhuys3b2eae32015-10-28 16:35:08 +000033import org.junit.Before;
34import org.junit.Test;
35import org.junit.runner.RunWith;
36import org.junit.runners.JUnit4;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000037
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000038/**
39 * Unit tests for {@link DiffAwarenessManager}, especially of the fact that it works in a sequential
40 * manner and of its correctness in the presence of unprocesed diffs.
41 */
Han-Wen Nienhuys3b2eae32015-10-28 16:35:08 +000042@RunWith(JUnit4.class)
43public class DiffAwarenessManagerTest {
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000044 private FileSystem fs;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000045 protected EventCollectionApparatus events;
46
Han-Wen Nienhuys3b2eae32015-10-28 16:35:08 +000047 @Before
Florian Weikert92b22362015-12-03 10:17:18 +000048 public final void createFileSystem() throws Exception {
ccalvarinc9efd062018-07-27 12:46:46 -070049 fs = new InMemoryFileSystem();
Florian Weikert92b22362015-12-03 10:17:18 +000050 }
51
52 @Before
53 public final void initializeEventCollectionApparatus() {
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000054 events = new EventCollectionApparatus();
55 events.setFailFast(false);
56 }
57
Han-Wen Nienhuys3b2eae32015-10-28 16:35:08 +000058 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000059 public void testEverythingModifiedIfNoDiffAwareness() throws Exception {
tomluee6a6862018-01-17 14:36:26 -080060 Root pathEntry = Root.fromPath(fs.getPath("/pathEntry"));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000061 DiffAwarenessFactoryStub factory = new DiffAwarenessFactoryStub();
62 DiffAwarenessManager manager = new DiffAwarenessManager(ImmutableList.of(factory));
lberkiaea56b32017-05-30 12:35:33 +020063 assertWithMessage("Expected EVERYTHING_MODIFIED since there are no factories")
64 .that(
65 manager
juliexxia618a0762018-08-17 08:33:52 -070066 .getDiff(events.reporter(), pathEntry, OptionsProvider.EMPTY)
lberkiaea56b32017-05-30 12:35:33 +020067 .getModifiedFileSet())
68 .isEqualTo(ModifiedFileSet.EVERYTHING_MODIFIED);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000069 events.assertNoWarningsOrErrors();
70 }
71
Han-Wen Nienhuys3b2eae32015-10-28 16:35:08 +000072 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000073 public void testResetAndSetPathEntriesCallClose() throws Exception {
tomluee6a6862018-01-17 14:36:26 -080074 Root pathEntry = Root.fromPath(fs.getPath("/pathEntry"));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000075 ModifiedFileSet diff = ModifiedFileSet.NOTHING_MODIFIED;
76 DiffAwarenessStub diffAwareness1 = new DiffAwarenessStub(ImmutableList.of(diff));
77 DiffAwarenessStub diffAwareness2 = new DiffAwarenessStub(ImmutableList.of(diff));
78 DiffAwarenessFactoryStub factory = new DiffAwarenessFactoryStub();
79 factory.inject(pathEntry, diffAwareness1);
80 DiffAwarenessManager manager = new DiffAwarenessManager(ImmutableList.of(factory));
juliexxia618a0762018-08-17 08:33:52 -070081 manager.getDiff(events.reporter(), pathEntry, OptionsProvider.EMPTY);
lberkiaea56b32017-05-30 12:35:33 +020082 assertWithMessage("diffAwareness1 shouldn't have been closed yet")
83 .that(diffAwareness1.closed())
84 .isFalse();
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000085 manager.reset();
lberkiaea56b32017-05-30 12:35:33 +020086 assertWithMessage("diffAwareness1 should have been closed by reset")
87 .that(diffAwareness1.closed())
88 .isTrue();
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000089 factory.inject(pathEntry, diffAwareness2);
juliexxia618a0762018-08-17 08:33:52 -070090 manager.getDiff(events.reporter(), pathEntry, OptionsProvider.EMPTY);
lberkiaea56b32017-05-30 12:35:33 +020091 assertWithMessage("diffAwareness2 shouldn't have been closed yet")
92 .that(diffAwareness2.closed())
93 .isFalse();
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000094 events.assertNoWarningsOrErrors();
95 }
96
Han-Wen Nienhuys3b2eae32015-10-28 16:35:08 +000097 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000098 public void testHandlesUnprocessedDiffs() throws Exception {
tomluee6a6862018-01-17 14:36:26 -080099 Root pathEntry = Root.fromPath(fs.getPath("/pathEntry"));
nharmatab4060b62017-04-04 17:11:39 +0000100 ModifiedFileSet diff1 = ModifiedFileSet.builder().modify(PathFragment.create("file1")).build();
101 ModifiedFileSet diff2 = ModifiedFileSet.builder().modify(PathFragment.create("file2")).build();
102 ModifiedFileSet diff3 = ModifiedFileSet.builder().modify(PathFragment.create("file3")).build();
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000103 DiffAwarenessStub diffAwareness =
104 new DiffAwarenessStub(ImmutableList.of(diff1, diff2, diff3, DiffAwarenessStub.BROKEN_DIFF));
105 DiffAwarenessFactoryStub factory = new DiffAwarenessFactoryStub();
106 factory.inject(pathEntry, diffAwareness);
107 DiffAwarenessManager manager = new DiffAwarenessManager(ImmutableList.of(factory));
Ulf Adamsde14ade2016-10-14 14:20:31 +0000108 ProcessableModifiedFileSet firstProcessableDiff =
juliexxia618a0762018-08-17 08:33:52 -0700109 manager.getDiff(events.reporter(), pathEntry, OptionsProvider.EMPTY);
lberkiaea56b32017-05-30 12:35:33 +0200110 assertWithMessage("Expected EVERYTHING_MODIFIED on first call to getDiff")
111 .that(firstProcessableDiff.getModifiedFileSet())
112 .isEqualTo(ModifiedFileSet.EVERYTHING_MODIFIED);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000113 firstProcessableDiff.markProcessed();
Ulf Adamsde14ade2016-10-14 14:20:31 +0000114 ProcessableModifiedFileSet processableDiff1 =
juliexxia618a0762018-08-17 08:33:52 -0700115 manager.getDiff(events.reporter(), pathEntry, OptionsProvider.EMPTY);
lberkiaea56b32017-05-30 12:35:33 +0200116 assertThat(processableDiff1.getModifiedFileSet()).isEqualTo(diff1);
Ulf Adamsde14ade2016-10-14 14:20:31 +0000117 ProcessableModifiedFileSet processableDiff2 =
juliexxia618a0762018-08-17 08:33:52 -0700118 manager.getDiff(events.reporter(), pathEntry, OptionsProvider.EMPTY);
lberkiaea56b32017-05-30 12:35:33 +0200119 assertThat(processableDiff2.getModifiedFileSet())
120 .isEqualTo(ModifiedFileSet.union(diff1, diff2));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000121 processableDiff2.markProcessed();
Ulf Adamsde14ade2016-10-14 14:20:31 +0000122 ProcessableModifiedFileSet processableDiff3 =
juliexxia618a0762018-08-17 08:33:52 -0700123 manager.getDiff(events.reporter(), pathEntry, OptionsProvider.EMPTY);
lberkiaea56b32017-05-30 12:35:33 +0200124 assertThat(processableDiff3.getModifiedFileSet()).isEqualTo(diff3);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000125 events.assertNoWarningsOrErrors();
Ulf Adamsde14ade2016-10-14 14:20:31 +0000126 ProcessableModifiedFileSet processableDiff4 =
juliexxia618a0762018-08-17 08:33:52 -0700127 manager.getDiff(events.reporter(), pathEntry, OptionsProvider.EMPTY);
lberkiaea56b32017-05-30 12:35:33 +0200128 assertThat(processableDiff4.getModifiedFileSet())
129 .isEqualTo(ModifiedFileSet.EVERYTHING_MODIFIED);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000130 events.assertContainsWarning("error");
131 }
132
Han-Wen Nienhuys3b2eae32015-10-28 16:35:08 +0000133 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000134 public void testHandlesBrokenDiffs() throws Exception {
tomluee6a6862018-01-17 14:36:26 -0800135 Root pathEntry = Root.fromPath(fs.getPath("/pathEntry"));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000136 DiffAwarenessFactoryStub factory1 = new DiffAwarenessFactoryStub();
137 DiffAwarenessStub diffAwareness1 =
138 new DiffAwarenessStub(ImmutableList.<ModifiedFileSet>of(), 1);
139 factory1.inject(pathEntry, diffAwareness1);
140 DiffAwarenessFactoryStub factory2 = new DiffAwarenessFactoryStub();
nharmatab4060b62017-04-04 17:11:39 +0000141 ModifiedFileSet diff2 = ModifiedFileSet.builder().modify(PathFragment.create("file2")).build();
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000142 DiffAwarenessStub diffAwareness2 =
143 new DiffAwarenessStub(ImmutableList.of(diff2, DiffAwarenessStub.BROKEN_DIFF));
144 factory2.inject(pathEntry, diffAwareness2);
145 DiffAwarenessFactoryStub factory3 = new DiffAwarenessFactoryStub();
nharmatab4060b62017-04-04 17:11:39 +0000146 ModifiedFileSet diff3 = ModifiedFileSet.builder().modify(PathFragment.create("file3")).build();
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000147 DiffAwarenessStub diffAwareness3 = new DiffAwarenessStub(ImmutableList.of(diff3));
148 factory3.inject(pathEntry, diffAwareness3);
149 DiffAwarenessManager manager =
150 new DiffAwarenessManager(ImmutableList.of(factory1, factory2, factory3));
151
Ulf Adamsde14ade2016-10-14 14:20:31 +0000152 ProcessableModifiedFileSet processableDiff =
juliexxia618a0762018-08-17 08:33:52 -0700153 manager.getDiff(events.reporter(), pathEntry, OptionsProvider.EMPTY);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000154 events.assertNoWarningsOrErrors();
lberkiaea56b32017-05-30 12:35:33 +0200155 assertWithMessage("Expected EVERYTHING_MODIFIED on first call to getDiff for diffAwareness1")
156 .that(processableDiff.getModifiedFileSet())
157 .isEqualTo(ModifiedFileSet.EVERYTHING_MODIFIED);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000158 processableDiff.markProcessed();
159
juliexxia618a0762018-08-17 08:33:52 -0700160 processableDiff = manager.getDiff(events.reporter(), pathEntry, OptionsProvider.EMPTY);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000161 events.assertContainsEventWithFrequency("error in getCurrentView", 1);
lberkiaea56b32017-05-30 12:35:33 +0200162 assertWithMessage("Expected EVERYTHING_MODIFIED because of broken getCurrentView")
163 .that(processableDiff.getModifiedFileSet())
164 .isEqualTo(ModifiedFileSet.EVERYTHING_MODIFIED);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000165 processableDiff.markProcessed();
166 factory1.remove(pathEntry);
167
juliexxia618a0762018-08-17 08:33:52 -0700168 processableDiff = manager.getDiff(events.reporter(), pathEntry, OptionsProvider.EMPTY);
lberkiaea56b32017-05-30 12:35:33 +0200169 assertWithMessage("Expected EVERYTHING_MODIFIED on first call to getDiff for diffAwareness2")
170 .that(processableDiff.getModifiedFileSet())
171 .isEqualTo(ModifiedFileSet.EVERYTHING_MODIFIED);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000172 processableDiff.markProcessed();
173
juliexxia618a0762018-08-17 08:33:52 -0700174 processableDiff = manager.getDiff(events.reporter(), pathEntry, OptionsProvider.EMPTY);
lberkiaea56b32017-05-30 12:35:33 +0200175 assertThat(processableDiff.getModifiedFileSet()).isEqualTo(diff2);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000176 processableDiff.markProcessed();
177
juliexxia618a0762018-08-17 08:33:52 -0700178 processableDiff = manager.getDiff(events.reporter(), pathEntry, OptionsProvider.EMPTY);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000179 events.assertContainsEventWithFrequency("error in getDiff", 1);
lberkiaea56b32017-05-30 12:35:33 +0200180 assertWithMessage("Expected EVERYTHING_MODIFIED because of broken getDiff")
181 .that(processableDiff.getModifiedFileSet())
182 .isEqualTo(ModifiedFileSet.EVERYTHING_MODIFIED);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000183 processableDiff.markProcessed();
184 factory2.remove(pathEntry);
185
juliexxia618a0762018-08-17 08:33:52 -0700186 processableDiff = manager.getDiff(events.reporter(), pathEntry, OptionsProvider.EMPTY);
lberkiaea56b32017-05-30 12:35:33 +0200187 assertWithMessage("Expected EVERYTHING_MODIFIED on first call to getDiff for diffAwareness3")
188 .that(processableDiff.getModifiedFileSet())
189 .isEqualTo(ModifiedFileSet.EVERYTHING_MODIFIED);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000190 processableDiff.markProcessed();
191
juliexxia618a0762018-08-17 08:33:52 -0700192 processableDiff = manager.getDiff(events.reporter(), pathEntry, OptionsProvider.EMPTY);
lberkiaea56b32017-05-30 12:35:33 +0200193 assertThat(processableDiff.getModifiedFileSet()).isEqualTo(diff3);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000194 processableDiff.markProcessed();
195 }
196
197 private static class DiffAwarenessFactoryStub implements DiffAwareness.Factory {
198
tomluee6a6862018-01-17 14:36:26 -0800199 private final Map<Root, DiffAwareness> diffAwarenesses = Maps.newHashMap();
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000200
tomluee6a6862018-01-17 14:36:26 -0800201 public void inject(Root pathEntry, DiffAwareness diffAwareness) {
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000202 diffAwarenesses.put(pathEntry, diffAwareness);
203 }
204
tomluee6a6862018-01-17 14:36:26 -0800205 public void remove(Root pathEntry) {
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000206 diffAwarenesses.remove(pathEntry);
207 }
208
209 @Override
210 @Nullable
tomluee6a6862018-01-17 14:36:26 -0800211 public DiffAwareness maybeCreate(Root pathEntry) {
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000212 return diffAwarenesses.get(pathEntry);
213 }
214 }
215
216 private static class DiffAwarenessStub implements DiffAwareness {
217
218 public static final ModifiedFileSet BROKEN_DIFF =
nharmatab4060b62017-04-04 17:11:39 +0000219 ModifiedFileSet.builder().modify(PathFragment.create("special broken marker")).build();
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000220
221 private boolean closed = false;
222 private int curSequenceNum = 0;
223 private final List<ModifiedFileSet> sequentialDiffs;
224 private final int brokenViewNum;
225
226 public DiffAwarenessStub(List<ModifiedFileSet> sequentialDiffs) {
227 this(sequentialDiffs, -1);
228 }
229
230 public DiffAwarenessStub(List<ModifiedFileSet> sequentialDiffs, int brokenViewNum) {
231 this.sequentialDiffs = sequentialDiffs;
232 this.brokenViewNum = brokenViewNum;
233 }
234
235 private static class ViewStub implements DiffAwareness.View {
236 private final int sequenceNum;
237
238 public ViewStub(int sequenceNum) {
239 this.sequenceNum = sequenceNum;
240 }
241 }
242
243 @Override
juliexxia618a0762018-08-17 08:33:52 -0700244 public View getCurrentView(OptionsProvider options) throws BrokenDiffAwarenessException {
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000245 if (curSequenceNum == brokenViewNum) {
246 throw new BrokenDiffAwarenessException("error in getCurrentView");
247 }
248 return new ViewStub(curSequenceNum++);
249 }
250
251 @Override
252 public ModifiedFileSet getDiff(View oldView, View newView) throws BrokenDiffAwarenessException {
253 assertThat(oldView).isInstanceOf(ViewStub.class);
254 assertThat(newView).isInstanceOf(ViewStub.class);
255 ViewStub oldViewStub = (ViewStub) oldView;
256 ViewStub newViewStub = (ViewStub) newView;
257 Preconditions.checkState(newViewStub.sequenceNum >= oldViewStub.sequenceNum);
258 ModifiedFileSet diff = ModifiedFileSet.NOTHING_MODIFIED;
259 for (int num = oldViewStub.sequenceNum; num < newViewStub.sequenceNum; num++) {
260 ModifiedFileSet incrementalDiff = sequentialDiffs.get(num);
261 if (incrementalDiff == BROKEN_DIFF) {
262 throw new BrokenDiffAwarenessException("error in getDiff");
263 }
264 diff = ModifiedFileSet.union(diff, incrementalDiff);
265 }
266 return diff;
267 }
268
269 @Override
270 public String name() {
271 return "testingstub";
272 }
273
274 @Override
275 public void close() {
276 closed = true;
277 }
278
279 public boolean closed() {
280 return closed;
281 }
282 }
283}