blob: 640483005c0d0ce40b6539d7de0019ece0ba1645 [file] [log] [blame]
// Copyright 2015 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.skyframe;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.skyframe.InMemoryGraphImpl.EdgelessInMemoryGraphImpl;
import com.google.devtools.build.skyframe.QueryableGraph.Reason;
import org.junit.Test;
/** Tests for {@link InMemoryGraphImpl}. */
public class InMemoryGraphTest extends GraphTest {
@Override
protected Version getStartingVersion() {
return IntVersion.of(0);
}
@Override
protected Version getNextVersion(Version v) {
Preconditions.checkState(v instanceof IntVersion);
return ((IntVersion) v).next();
}
@Override
protected void makeGraph() {
graph = new InMemoryGraphImpl();
}
@Override
protected ProcessableGraph getGraph(Version version) {
return graph;
}
/** Tests for {@link EdgelessInMemoryGraphImpl}. */
public static final class EdgelessInMemoryGraphTest extends InMemoryGraphTest {
@Override
protected void makeGraph() {}
@Override
protected ProcessableGraph getGraph(Version version) {
return new EdgelessInMemoryGraphImpl(/* usePooledInterning= */ true);
}
@Override
protected Version getStartingVersion() {
return Version.constant();
}
@Override
protected Version getNextVersion(Version version) {
throw new UnsupportedOperationException();
}
@Override
protected boolean shouldTestIncrementality() {
return false;
}
}
public static final class SkyKeyWithSkyKeyInterner extends AbstractSkyKey<String> {
private static final SkyKeyInterner<SkyKeyWithSkyKeyInterner> interner = SkyKey.newInterner();
static SkyKeyWithSkyKeyInterner create(String arg) {
return interner.intern(new SkyKeyWithSkyKeyInterner(arg));
}
private SkyKeyWithSkyKeyInterner(String arg) {
super(arg);
}
@Override
public SkyFunctionName functionName() {
return SkyFunctionName.FOR_TESTING;
}
@Override
public SkyKeyInterner<SkyKeyWithSkyKeyInterner> getSkyKeyInterner() {
return interner;
}
}
@Test
public void createIfAbsentBatch_skyKeyWithSkyKeyInterner() throws InterruptedException {
SkyKey cat = SkyKeyWithSkyKeyInterner.create("cat");
// Insert cat SkyKey into graph.
// (1) result of getting cat node from graph should not be null;
// (2) when re-creating cat SkyKeyWithSkyKeyInterner object, it should retrieve the instance
// from global pool (graph), which is also the same instance as the original one.
graph.createIfAbsentBatch(null, Reason.OTHER, ImmutableList.of(cat));
assertThat(graph.get(null, Reason.OTHER, cat)).isNotNull();
assertThat(SkyKeyWithSkyKeyInterner.create("cat")).isSameInstanceAs(cat);
// Remove cat SkyKey from graph.
// (1) result of getting cat node from graph should be null, indicating the cat key has been
// removed from the global pool (graph);
// (2) since when removing key from global pool (graph), the removed key will be re-interned
// back to weak interner. So re-creating an equal "cat" object from SkyKeyWithSkyKeyInterner
// will result in the same instance to be returned (no new instance will be created).
graph.remove(cat);
assertThat(graph.get(null, Reason.OTHER, cat)).isNull();
assertThat(SkyKeyWithSkyKeyInterner.create("cat")).isSameInstanceAs(cat);
}
@Test
public void cleanupPool_weakInternerReintern() throws InterruptedException {
SkyKey cat = SkyKeyWithSkyKeyInterner.create("cat");
graph.createIfAbsentBatch(null, Reason.OTHER, ImmutableList.of(cat));
assertThat(graph.get(null, Reason.OTHER, cat)).isNotNull();
assertThat(graph).isInstanceOf(InMemoryGraphImpl.class);
((InMemoryGraphImpl) graph).cleanupInterningPools();
// When re-creating a cat SkyKeyWithSkyKeyInterner, we expect to get the original instance. Pool
// cleaning up re-interns the cat instance back to the weak interner, and thus, no new instance
// is created.
assertThat(SkyKeyWithSkyKeyInterner.create("cat")).isSameInstanceAs(cat);
}
@Test
public void removePackageNode_notPresentInGraph() throws Exception {
PackageIdentifier packageIdentifier = PackageIdentifier.createUnchecked("repo", "hello");
graph.remove(packageIdentifier);
assertThat(graph.get(null, Reason.OTHER, packageIdentifier)).isNull();
}
@Test
public void removePackageNode_noValueWeakInternLabelsNoCrash() throws Exception {
PackageIdentifier packageIdentifier = PackageIdentifier.createUnchecked("repo", "hello");
graph.createIfAbsentBatch(null, Reason.OTHER, ImmutableList.of(packageIdentifier));
NodeEntry entry = graph.get(null, Reason.OTHER, packageIdentifier);
assertThat(entry.toValue()).isNull();
graph.remove(packageIdentifier);
assertThat(graph.get(null, Reason.OTHER, packageIdentifier)).isNull();
}
}