blob: 5727b3d666ec2f0440fa2db331cf4405dcc8ce94 [file] [log] [blame]
// Copyright 2022 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.starlarkbuildapi.core;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.truth.Truth.assertThat;
import static java.util.Arrays.stream;
import com.google.devtools.build.lib.cmdline.BazelCompileContext;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import net.starlark.java.eval.GuardedValue;
import net.starlark.java.eval.StarlarkSemantics;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public final class ContextGuardedValueTest {
/**
* We want to make sure the empty string doesn't result in "allow everything". That would be bad.
* Most allowlists have an entry like ("", "tools/build_defs/lang") for usage within Google.
*/
@Test
public void emptyRepoAllowed_doesntMatchNonAllowed() throws Exception {
assertNotAllowed("@mylang//bar:baz", "@//tools/lang");
}
@Test
public void emptyRepoAllowed_matchesAllowed() throws Exception {
assertAllowed("@//tools/lang", "@//tools/lang");
}
@Test
public void workspaceRepo_matchesAllowedRepo() throws Exception {
assertAllowed("@rules_foo//tools/lang", "@rules_foo//");
}
@Test
public void workspaceRepo_doesntMatchCommonSubstr() throws Exception {
assertNotAllowed("@my_rules_foo_helper//tools/lang", "@rules_foo//");
}
@Test
public void bzlmodRepo_matchesStart() throws Exception {
assertAllowed("@rules_foo~override//tools/lang", "@rules_foo//");
assertAllowed("@rules_foo~1.2.3//tools/lang", "@rules_foo//");
}
@Test
public void bzlmodRepo_matchesWithin() throws Exception {
assertAllowed("@rules_lang~override~ext~foo_helper//tools/lang", "@foo_helper//");
}
@Test
public void bzlmodRepo_doesntMatchCommonSubstr() throws Exception {
assertNotAllowed("@rules_lang~override~ext~my_foo_helper_lib//tools/lang", "@foo_helper//");
}
@Test
public void reposWithDotsDontMatch() throws Exception {
assertNotAllowed("@my.lang//foo", "@my_lang//");
}
@Test
public void verifySomeRealisticCases() throws Exception {
// Python with workspace
assertAllowed("@//tools/build_defs/python/private", "@//tools/build_defs/python");
assertAllowed("@rules_python//python/private", "@rules_python//");
// Python with bzlmod
assertAllowed(
"@rules_python~override~internal_deps~rules_python_internal//private", "@rules_python//");
// CC with workspace
assertAllowed("@//tools/build_defs/cc", "@//tools/build_defs/cc");
assertNotAllowed("@rules_cc_helper//tools/build_defs/cc", "@rules_cc//");
// CC with Bzlmod
assertAllowed("@rules_cc~1.2.3~ext_name~local_cc_config//foo", "@local_cc_config//");
}
private Object createClientData(String callerLabelStr) {
return BazelCompileContext.create(
Label.parseCanonicalUnchecked(callerLabelStr), "unused_caller.bzl");
}
private GuardedValue createGuard(Object clientData, String... allowedLabelStrs) throws Exception {
var allowed =
stream(allowedLabelStrs)
.map(
labelStr -> {
try {
return PackageIdentifier.parse(labelStr);
} catch (LabelSyntaxException e) {
// We have to manually catch and re-throw this, otherwise Java is unhappy.
throw new RuntimeException(e);
}
})
.collect(toImmutableSet());
return ContextGuardedValue.onlyInAllowedRepos(clientData, allowed);
}
private void assertAllowed(String callerLabelStr, String... allowedLabelStrs) throws Exception {
var clientData = createClientData(callerLabelStr);
var guard = createGuard(clientData, allowedLabelStrs);
assertThat(guard.isObjectAccessibleUsingSemantics(StarlarkSemantics.DEFAULT, clientData))
.isTrue();
}
private void assertNotAllowed(String callerLabelStr, String... allowedLabelStrs)
throws Exception {
var clientData = createClientData(callerLabelStr);
var guard = createGuard(clientData, allowedLabelStrs);
assertThat(guard.isObjectAccessibleUsingSemantics(StarlarkSemantics.DEFAULT, clientData))
.isFalse();
}
}