Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intellij integration test #6909

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ build --java_language_version=17 --java_runtime_version=17

# Delete test data packages, needed for bazel integration tests. Update by running the following command:
# bazel run @rules_bazel_integration_test//tools:update_deleted_packages
build --deleted_packages=aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/testdata,clwb/tests/projects/simple/main,clwb/tests/projects/virtual_includes/lib/strip_absolut,clwb/tests/projects/virtual_includes/lib/strip_relative,clwb/tests/projects/virtual_includes/main
query --deleted_packages=aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/testdata,clwb/tests/projects/simple/main,clwb/tests/projects/virtual_includes/lib/strip_absolut,clwb/tests/projects/virtual_includes/lib/strip_relative,clwb/tests/projects/virtual_includes/main
build --deleted_packages=aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/testdata,clwb/tests/projects/simple/main,clwb/tests/projects/virtual_includes/lib/strip_absolut,clwb/tests/projects/virtual_includes/lib/strip_relative,clwb/tests/projects/virtual_includes/main,ijwb/tests/projects/simple
query --deleted_packages=aspect/testing/tests/src/com/google/idea/blaze/aspect/integration/testdata,clwb/tests/projects/simple/main,clwb/tests/projects/virtual_includes/lib/strip_absolut,clwb/tests/projects/virtual_includes/lib/strip_relative,clwb/tests/projects/virtual_includes/main,ijwb/tests/projects/simple

common --enable_bzlmod
common --enable_workspace # to load rules_scala from WORKSPACE.bzlmod
Expand Down
Empty file removed aspect_template/MODULE.bazel
Empty file.
21 changes: 21 additions & 0 deletions base/tests/utils/heavy/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
load("@rules_java//java:defs.bzl", "java_library")
load("//:build-visibility.bzl", "DEFAULT_TEST_VISIBILITY")

java_library(
name = "lib",
srcs = glob(["src/**/*.java"]),
visibility = DEFAULT_TEST_VISIBILITY,
testonly = True,
deps = [
"//base",
"//shared",
"//testing:lib",
"//common/util:process",
"//intellij_platform_sdk:jsr305",
"//intellij_platform_sdk:plugin_api_for_tests",
"//intellij_platform_sdk:test_libs",
"//sdkcompat",
"@junit//jar",
"@org_opentest4j_opentest4j//jar",
]
)
32 changes: 26 additions & 6 deletions clwb/test_defs.bzl → base/tests/utils/heavy/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ version_specific_args = {
},
}

def clwb_integration_test(name, project, srcs, deps = []):
def _integration_test(name, project, srcs, deps, test_package_root, runtime_deps):
runner = name + "_runner"

intellij_integration_test_suite(
name = runner,
srcs = srcs + native.glob(["tests/integrationtests/com/google/idea/blaze/clwb/base/*.java"]),
test_package_root = "com.google.idea.blaze.clwb",
runtime_deps = [":clwb_bazel"],
srcs = srcs,
test_package_root = test_package_root,
runtime_deps = runtime_deps,
data = [
"//aspect:aspect_files",
"//aspect_template:aspect_files",
Expand All @@ -34,11 +34,11 @@ def clwb_integration_test(name, project, srcs, deps = []):
# disables the default bazel security manager, causes tests to fail on windows
"-Dcom.google.testing.junit.runner.shouldInstallTestSecurityManager=false",
# fixes preferences not writable on mac
"-Djava.util.prefs.PreferencesFactory=com.google.idea.blaze.clwb.base.InMemoryPreferencesFactory",
"-Djava.util.prefs.PreferencesFactory=com.google.idea.blaze.base.InMemoryPreferencesFactory",
],
deps = deps + [
":clwb_lib",
"//base",
"//base/tests/utils/heavy:lib",
"//shared",
"//common/util:process",
"//intellij_platform_sdk:jsr305",
Expand Down Expand Up @@ -73,3 +73,23 @@ def clwb_integration_test(name, project, srcs, deps = []):
bazel_binaries.versions.all,
),
)

def clwb_integration_test(name, project, srcs, deps = []):
_integration_test(
name,
project,
srcs,
deps + ["//clwb:clwb_lib"],
test_package_root = "com.google.idea.blaze.clwb",
runtime_deps = ["//clwb:clwb_bazel"],
)

def ijwb_integration_test(name, project, srcs, deps = []):
_integration_test(
name,
project,
srcs,
deps + ["//ijwb:ijwb_lib"],
test_package_root = "com.google.idea.blaze.ijwb",
runtime_deps = ["//ijwb:ijwb_bazel"],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
package com.google.idea.blaze.base;

import static com.google.common.truth.Truth.assertThat;

import com.google.idea.blaze.base.async.process.ExternalTask;
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
import com.google.idea.blaze.base.project.AutoImportProjectOpenProcessor;
import com.google.idea.blaze.base.project.ExtendableBazelProjectCreator;
import com.google.idea.blaze.base.projectview.ProjectView;
import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.projectview.section.sections.TextBlock;
import com.google.idea.blaze.base.projectview.section.sections.TextBlockSection;
import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.settings.BlazeUserSettings;
import com.google.idea.blaze.base.settings.BuildSystemName;
import com.google.idea.blaze.base.sync.BlazeSyncParams;
import com.google.idea.blaze.base.sync.SyncMode;
import com.google.idea.blaze.base.sync.SyncPhaseCoordinator;
import com.google.idea.blaze.base.sync.aspects.strategy.AspectRepositoryProvider;
import com.google.idea.blaze.base.sync.data.BlazeDataStorage;
import com.google.idea.blaze.base.sync.workspace.WorkspacePathResolverImpl;
import com.google.idea.blaze.base.toolwindow.TasksToolWindowFactory;
import com.google.idea.blaze.base.wizard2.BlazeProjectCommitException;
import com.google.idea.blaze.base.wizard2.BlazeProjectImportBuilder;
import com.google.idea.blaze.base.wizard2.CreateFromScratchProjectViewOption;
import com.google.idea.blaze.base.wizard2.WorkspaceTypeData;
import com.google.idea.testing.ServiceHelper;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.testFramework.HeavyPlatformTestCase;
import com.intellij.testFramework.IndexingTestUtil;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.toolWindow.ToolWindowHeadlessManagerImpl;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import org.intellij.lang.annotations.Language;

public abstract class BazelHeavyIntegrationTest extends HeavyPlatformTestCase {
protected VirtualFile myProjectRoot;

/**
* Normalizes an absolut posix path for windows. Since tests have to be run with `MSYS_NO_PATHCONV`
* set to true. Paths are no longer converted by the bazel test setup.
*/
private static String normalizePath(String path) {
if (!SystemInfo.isWindows || !path.startsWith("/")) {
return path;
}

final var parts = path.substring(1).split("/");
parts[0] = parts[0] + ":";

return String.join("\\", parts);
}

/**
* Gets the path to the test project and performs some basic checks. The path
* is provided by `bazel_integration_test` rule in the `BIT_WORKSPACE_DIR`
* environment variable.
*/
private static File getTestProjectRoot() {
final var bitWorkspaceDir = System.getenv("BIT_WORKSPACE_DIR");
assertThat(bitWorkspaceDir).isNotNull();

final var file = new File(normalizePath(bitWorkspaceDir));
assertExists(file);

return file;
}

/**
* Gets the path to the bazelisk wrapper script and performs some basic checks.
* The path is provided by `bazel_integration_test` rule in the `BIT_BAZEL_BINARY`
* environment variable.
*/
private static String getTestBazelPath() throws Exception {
final var bitBazelBinary = System.getenv("BIT_BAZEL_BINARY");
assertThat(bitBazelBinary).isNotNull();

final var file = new File(normalizePath(bitBazelBinary));
assertExists(file);

final var errStream = new ByteArrayOutputStream();

// run bazel binary in project root to avoid downloading it twice
final var result = ExternalTask.builder(getTestProjectRoot())
.args(file.getAbsolutePath(), "version")
.stderr(errStream)
.build()
.runAsync()
.get(1, TimeUnit.MINUTES);

if (result != 0) {
fail("cannot run bazel binary: " + errStream);
}

return file.getAbsolutePath();
}

@Override
protected void setUp() throws Exception {
super.setUp();

final var bazelBinary = getTestBazelPath();
BlazeUserSettings.getInstance().setBazelBinaryPath(bazelBinary);

// register the tasks toolwindow, needs to be done manually
final var windowManager = (ToolWindowHeadlessManagerImpl) ToolWindowManager.getInstance(myProject);
windowManager.doRegisterToolWindow(TasksToolWindowFactory.ID);

// override aspect repository, because they are in a different place during testing
ServiceHelper.registerExtensionFirst(
AspectRepositoryProvider.EP_NAME,
new TestAspectRepositoryProvider(),
getTestRootDisposable()
);

// create the temp directory, because CLion expected it to be present but bazel does not create it
final var tmpDir = new File(FileUtil.getTempDirectory());
tmpDir.mkdirs();
}

/**
* Very similar to {@link AutoImportProjectOpenProcessor}.
*
* However, it is not possible to use the auto import processor directly because it immediately runs a sync, and it
* is not possible to perform any kind of project setup between the import and the initial sync.
*/
@Override
protected void setUpProject() throws Exception {
final var rootFile = getTestProjectRoot();
myProjectRoot = HeavyPlatformTestCase.getVirtualFile(rootFile);

final var projectFile = new File(rootFile, BlazeDataStorage.PROJECT_DATA_SUBDIRECTORY);

try {
FileUtil.ensureExists(new File(projectFile, Project.DIRECTORY_STORE_FOLDER));
} catch (IOException e) {
fail("could not create project directory: " + e.getMessage());
}

final var name = rootFile.getName();
final var builder = new BlazeProjectImportBuilder();
final var root = new WorkspaceRoot(rootFile);

builder.builder().setWorkspaceData(
WorkspaceTypeData.builder()
.setWorkspaceName(rootFile.getName())
.setWorkspaceRoot(root)
.setCanonicalProjectDataLocation(rootFile)
.setFileBrowserRoot(rootFile)
.setWorkspacePathResolver(new WorkspacePathResolverImpl(root))
.setBuildSystem(BuildSystemName.Bazel)
.build()
);

final var projectViewLines = projectViewText().split("\n");
final var projectViewBuilder = ProjectView.builder();
projectViewBuilder.add(TextBlockSection.of(TextBlock.of(1, projectViewLines)));
final var projectView = projectViewBuilder.build();

builder.builder().setProjectView(projectView);
builder.builder().setProjectViewFile(new File(projectFile, ".bazelproject"));
builder.builder().setProjectViewSet(ProjectViewSet.builder().add(projectView).build());
builder.builder().setProjectViewOption(new CreateFromScratchProjectViewOption());
builder.builder().setProjectName(name);
builder.builder().setProjectDataDirectory(projectFile.getAbsolutePath());

try {
builder.builder().commit(); // set pending project settings
} catch (BlazeProjectCommitException e) {
fail("could not commit project: " + e.getMessage());
}

final var projectCreator = ExtendableBazelProjectCreator.getInstance();
final var projectOpt = projectCreator.createProject(builder, name, projectFile.getAbsolutePath());
if (projectOpt.isEmpty()) {
fail("could not create project");
}

myProject = projectOpt.get();
myProject.save();

if (!builder.validate(null, myProject)) {
fail("could not validate project");
}

builder.builder().commitToProject(myProject);
}

protected @Language("projectview") String projectViewText() {
return """
directories:
.

derive_targets_from_directories: true
""";
}

protected SyncOutput runSync(BlazeSyncParams params) {
final var context = BlazeContext.create();

final var output = new SyncOutput();
output.install(context);

final var future = CompletableFuture.runAsync(() -> {
SyncPhaseCoordinator.getInstance(myProject).runSync(params, true, context);
}, ApplicationManager.getApplication()::executeOnPooledThread);

while (!future.isDone()) {
PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue();
}

output.setHasErrors(context.hasErrors());
output.setHasWarnings(context.hasWarnings());

context.close();
LOG.info(String.format("PROJECT SYNC LOG:%n%s", output.collectLog()));

IndexingTestUtil.waitUntilIndexesAreReady(myProject);

return output;
}

protected BlazeSyncParams.Builder defaultSyncParams() {
return BlazeSyncParams.builder()
.setTitle("test sync")
.setSyncMode(SyncMode.FULL)
.setSyncOrigin("test")
.setAddProjectViewTargets(true);
}

protected VirtualFile findProjectFile(String relativePath) {
final var file = myProjectRoot.findFileByRelativePath(relativePath);
assertThat(file).isNotNull();

return file;
}

protected PsiFile findProjectPsiFile(String relativePath) {
final var file = PsiManager.getInstance(myProject).findFile(findProjectFile(relativePath));
assertThat(file).isNotNull();

return file;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.google.idea.blaze.clwb.base;
package com.google.idea.blaze.base;

import java.util.HashMap;
import java.util.Map;
Expand Down
Loading