Skip to content

Commit 2cf135d

Browse files
authored
✨ Add comprehensive integration test suite with CI/CD pipeline (#165)
* fixup Signed-off-by: Shawn Hurley <[email protected]> * remove runtime .metadata folder Signed-off-by: Shawn Hurley <[email protected]> * Commiting the specific changes for getting the integration tests working Signed-off-by: Shawn Hurley <[email protected]> * claude fixing tests Signed-off-by: Shawn Hurley <[email protected]> * another round of claude generation for the tests Signed-off-by: Shawn Hurley <[email protected]> * fixing up more tests Signed-off-by: Shawn Hurley <[email protected]> * claude fixed itself Signed-off-by: Shawn Hurley <[email protected]> * removing un-necessary change Signed-off-by: Shawn Hurley <[email protected]> * seeing if bumping version passes ci Signed-off-by: Shawn Hurley <[email protected]> * wonder if the cache is giving me issues Signed-off-by: Shawn Hurley <[email protected]> * turn of the UI when running the tests Signed-off-by: Shawn Hurley <[email protected]> * addressing code rabbit comments Signed-off-by: Shawn Hurley <[email protected]> * Add PackageUsageExample.java test file for PACKAGE location type testing This file demonstrates package usage through: - Import statements (java.util, javax.persistence) - Fully qualified names (java.sql.Connection, java.io.File, java.time.LocalDateTime) Used to test that PACKAGE location type (11) matches both imports and FQN usage. Signed-off-by: Shawn Hurley <[email protected]> --------- Signed-off-by: Shawn Hurley <[email protected]>
1 parent c0b7684 commit 2cf135d

File tree

73 files changed

+7116
-52
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+7116
-52
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
name: Phase 2 Integration Tests
2+
3+
on:
4+
push:
5+
branches: [ main, maven-index ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
unit-tests:
11+
name: Unit Tests (Phase 1)
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Set up JDK 17
17+
uses: actions/setup-java@v5
18+
with:
19+
java-version: '17'
20+
distribution: 'temurin'
21+
cache: maven
22+
23+
- name: Run unit tests
24+
run: mvn clean integration-test
25+
26+
- name: Upload test results
27+
if: always()
28+
uses: actions/upload-artifact@v4
29+
with:
30+
name: unit-test-results
31+
path: |
32+
**/target/surefire-reports/*.xml
33+
**/target/surefire-reports/*.txt
34+
35+
jdtls-integration-tests:
36+
name: JDT.LS Integration Tests (Phase 2)
37+
runs-on: ubuntu-latest
38+
needs: unit-tests
39+
40+
steps:
41+
- uses: actions/checkout@v4
42+
43+
- name: Set up JDK 17
44+
uses: actions/setup-java@v4
45+
with:
46+
java-version: '17'
47+
distribution: 'temurin'
48+
cache: maven
49+
50+
- name: Set up Go
51+
uses: actions/setup-go@v5
52+
with:
53+
go-version: '1.23.9'
54+
55+
- name: Install Podman
56+
run: |
57+
sudo apt-get update
58+
sudo apt-get -y install podman
59+
60+
- name: Verify Podman installation
61+
run: |
62+
podman --version
63+
podman info
64+
65+
- name: Build JDT.LS container image with Podman
66+
run: |
67+
podman build -t jdtls-analyzer:test .
68+
69+
- name: Run Phase 2 integration tests in container
70+
run: |
71+
podman run --rm \
72+
-v "$(pwd)/java-analyzer-bundle.test:/tests:Z" \
73+
-e WORKSPACE_DIR=/tests/projects \
74+
-e JDTLS_PATH=/jdtls \
75+
--workdir /tests/integration \
76+
--entrypoint /bin/sh \
77+
jdtls-analyzer:test \
78+
-c "microdnf install -y golang && cd /tests/integration && go mod download && go test -v"
79+
timeout-minutes: 15

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,10 @@ target/
44
*.iml
55
.DS_Store
66
.gradle/
7+
8+
# Eclipse metadata
9+
**/.metadata/
10+
.classpath
11+
.project
12+
.settings/
13+
**/.plugins/

Dockerfile

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ FROM registry.access.redhat.com/ubi9/ubi AS addon-build
2222
RUN dnf install -y maven-openjdk17 && dnf clean all && rm -rf /var/cache/dnf
2323
WORKDIR /app
2424
COPY ./ /app/
25-
RUN export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
26-
RUN JAVA_HOME=/usr/lib/jvm/java-17-openjdk mvn clean install -DskipTests=true
25+
ENV JAVA_HOME /usr/lib/jvm/java-17-openjdk
26+
RUN mvn clean install -DskipTests=true
2727

2828
FROM registry.access.redhat.com/ubi9/ubi-minimal AS index-download
2929
RUN microdnf install -y wget zip && microdnf clean all && rm -rf /var/cache/dnf
@@ -51,7 +51,8 @@ COPY ./gradle/build.gradle /usr/local/etc/task.gradle
5151
COPY ./gradle/build-v9.gradle /usr/local/etc/task-v9.gradle
5252

5353
COPY --from=jdtls-download /jdtls /jdtls/
54-
COPY --from=addon-build /root/.m2/repository/io/konveyor/tackle/java-analyzer-bundle.core/1.0.0-SNAPSHOT/java-analyzer-bundle.core-1.0.0-SNAPSHOT.jar /jdtls/java-analyzer-bundle/java-analyzer-bundle.core/target/
54+
COPY --from=addon-build /root/.m2/repository/io/konveyor/tackle/java-analyzer-bundle.core/1.0.0-SNAPSHOT/java-analyzer-bundle.core-1.0.0-SNAPSHOT.jar /jdtls/plugins/
55+
COPY --from=addon-build /root/.m2/repository/io/konveyor/tackle/java-analyzer-bundle.core/1.0.0-SNAPSHOT/java-analyzer-bundle.core-1.0.0-SNAPSHOT.jar /jdtls/java-analyzer-bundle/java-analyzer-bundle.core/target/java-analyzer-bundle.core-1.0.0-SNAPSHOT.jar
5556
COPY --from=fernflower /output/fernflower.jar /bin/fernflower.jar
5657
COPY --from=maven-index /maven.default.index /usr/local/etc/maven.default.index
5758
COPY --from=index-download /maven-index-data/central.archive-metadata.txt /usr/local/etc/maven-index.txt

Dockerfile.test

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
FROM registry.access.redhat.com/ubi9/ubi AS jdtls-download
2+
WORKDIR /jdtls
3+
RUN curl -s -o jdtls.tar.gz https://download.eclipse.org/jdtls/milestones/1.38.0/jdt-language-server-1.38.0-202408011337.tar.gz &&\
4+
tar -xvf jdtls.tar.gz --no-same-owner &&\
5+
chmod 755 /jdtls/bin/jdtls &&\
6+
rm -rf jdtls.tar.gz
7+
8+
COPY jdtls-bin-override/jdtls.py /jdtls/bin/jdtls.py
9+
10+
FROM registry.access.redhat.com/ubi9/ubi AS maven-index
11+
COPY hack/maven.default.index /maven.default.index
12+
13+
FROM registry.access.redhat.com/ubi9/ubi AS fernflower
14+
RUN dnf install -y maven-openjdk17 wget --setopt=install_weak_deps=False && dnf clean all && rm -rf /var/cache/dnf
15+
RUN wget --quiet https://github.com/JetBrains/intellij-community/archive/refs/tags/idea/231.9011.34.tar.gz -O intellij-community.tar && tar xf intellij-community.tar intellij-community-idea-231.9011.34/plugins/java-decompiler/engine && rm -rf intellij-community.tar
16+
WORKDIR /intellij-community-idea-231.9011.34/plugins/java-decompiler/engine
17+
RUN export JAVA_HOME=/usr/lib/jvm/java-17-openjdk
18+
RUN ./gradlew build -x test && rm -rf /root/.gradle
19+
RUN mkdir /output && cp ./build/libs/fernflower.jar /output
20+
21+
FROM registry.access.redhat.com/ubi9/ubi-minimal AS index-download
22+
RUN microdnf install -y wget zip && microdnf clean all && rm -rf /var/cache/dnf
23+
WORKDIR /maven-index-data
24+
#TODO: get latest release when we get to update them periodically
25+
RUN wget --quiet https://github.com/konveyor/maven-search-index/releases/download/v0.0.1/maven-index-data-v0.0.1.zip -O maven-index-data.zip && unzip maven-index-data.zip && rm maven-index-data.zip
26+
27+
FROM registry.access.redhat.com/ubi9/ubi-minimal
28+
# Java 1.8 is required for backwards compatibility with older versions of Gradle
29+
RUN microdnf install -y python39 java-1.8.0-openjdk-devel java-21-openjdk-devel tar gzip zip --nodocs --setopt=install_weak_deps=0 && microdnf clean all && rm -rf /var/cache/dnf
30+
ENV JAVA_HOME /usr/lib/jvm/java-21-openjdk
31+
# Specify Java 1.8 home for usage with gradle wrappers
32+
ENV JAVA8_HOME /usr/lib/jvm/java-1.8.0-openjdk
33+
RUN curl -fsSL -o /tmp/apache-maven.tar.gz https://dlcdn.apache.org/maven/maven-3/3.9.11/binaries/apache-maven-3.9.11-bin.tar.gz && \
34+
tar -xzf /tmp/apache-maven.tar.gz -C /usr/local/ && \
35+
ln -s /usr/local/apache-maven-3.9.11/bin/mvn /usr/bin/mvn && \
36+
rm /tmp/apache-maven.tar.gz
37+
ENV M2_HOME /usr/local/apache-maven-3.9.11
38+
39+
# Copy "download sources" gradle task. This is needed to download project sources.
40+
RUN mkdir /root/.gradle
41+
COPY ./gradle/build.gradle /usr/local/etc/task.gradle
42+
COPY ./gradle/build-v9.gradle /usr/local/etc/task-v9.gradle
43+
44+
COPY --from=jdtls-download /jdtls /jdtls/
45+
COPY --from=fernflower /output/fernflower.jar /bin/fernflower.jar
46+
COPY --from=maven-index /maven.default.index /usr/local/etc/maven.default.index
47+
COPY --from=index-download /maven-index-data/central.archive-metadata.txt /usr/local/etc/maven-index.txt
48+
COPY --from=index-download /maven-index-data/central.archive-metadata.idx /usr/local/etc/maven-index.idx
49+
RUN microdnf install -y golang
50+
51+
RUN ln -sf /root/.m2 /.m2 && chgrp -R 0 /root && chmod -R g=u /root
52+
COPY java-analyzer-bundle.core/target/java-analyzer-bundle.core-1.0.0-SNAPSHOT.jar /jdtls/plugins/
53+
CMD [ "/jdtls/bin/jdtls" ]

Makefile

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Makefile for Java Analyzer Bundle
2+
# Replicates GitHub Actions CI/CD pipeline for local verification
3+
4+
.PHONY: help all ci clean clean-containers clean-go phase1 phase2 unit-tests build-container run-integration-tests
5+
6+
# Detect container runtime (prefer Podman, fallback to Docker)
7+
CONTAINER_RUNTIME := $(shell command -v podman 2>/dev/null || command -v docker 2>/dev/null)
8+
ifeq ($(CONTAINER_RUNTIME),)
9+
$(error Neither podman nor docker is installed)
10+
endif
11+
12+
# Set volume flags based on container runtime
13+
ifeq ($(findstring podman,$(CONTAINER_RUNTIME)),podman)
14+
VOLUME_FLAGS := :Z
15+
else
16+
VOLUME_FLAGS :=
17+
endif
18+
19+
# Variables
20+
IMAGE_NAME := jdtls-analyzer:test
21+
REPO_ROOT := $(shell pwd)
22+
GO_MODULE := java-analyzer-bundle.test/integration
23+
24+
# Default target
25+
help:
26+
@echo "======================================================================"
27+
@echo "Java Analyzer Bundle - CI/CD Verification Makefile"
28+
@echo "======================================================================"
29+
@echo ""
30+
@echo "Available targets:"
31+
@echo ""
32+
@echo " make ci - Run complete CI/CD pipeline (Phase 1 + 2)"
33+
@echo " make phase1 - Run Phase 1: Unit tests only"
34+
@echo " make phase2 - Run Phase 2: Integration tests only"
35+
@echo ""
36+
@echo "Phase 1 targets:"
37+
@echo " make unit-tests - Run Maven unit tests"
38+
@echo ""
39+
@echo "Phase 2 targets:"
40+
@echo " make build-container - Build JDT.LS container image"
41+
@echo " make run-integration-tests - Run integration tests in container"
42+
@echo ""
43+
@echo "Utility targets:"
44+
@echo " make clean - Clean all build artifacts"
45+
@echo " make clean-containers - Remove container images"
46+
@echo " make clean-go - Clean Go build artifacts"
47+
@echo ""
48+
@echo "Container runtime: $(CONTAINER_RUNTIME)"
49+
@echo "======================================================================"
50+
51+
# Run complete CI/CD pipeline
52+
ci: phase1 phase2
53+
@echo ""
54+
@echo "======================================================================"
55+
@echo "✓ Complete CI/CD Pipeline Succeeded!"
56+
@echo "======================================================================"
57+
58+
# Alias for consistency
59+
all: ci
60+
61+
# Phase 1: Unit Tests
62+
phase1: unit-tests
63+
@echo ""
64+
@echo "======================================================================"
65+
@echo "✓ Phase 1 Complete: Unit tests passed"
66+
@echo "======================================================================"
67+
68+
# Phase 2: Integration Tests
69+
phase2: build-container run-integration-tests
70+
@echo ""
71+
@echo "======================================================================"
72+
@echo "✓ Phase 2 Complete: Integration tests passed"
73+
@echo "======================================================================"
74+
75+
# Phase 1 Targets
76+
unit-tests:
77+
@echo "======================================================================"
78+
@echo "Phase 1: Running Unit Tests"
79+
@echo "======================================================================"
80+
@echo ""
81+
mvn clean integration-test
82+
83+
# Phase 2 Targets
84+
build-container:
85+
@echo ""
86+
@echo "======================================================================"
87+
@echo "Phase 2: Building JDT.LS Container Image"
88+
@echo "======================================================================"
89+
@echo ""
90+
@echo "Using container runtime: $(CONTAINER_RUNTIME)"
91+
@echo ""
92+
$(CONTAINER_RUNTIME) build -t $(IMAGE_NAME) -f Dockerfile.test .
93+
@echo ""
94+
@echo "✓ Container image built: $(IMAGE_NAME)"
95+
96+
run-integration-tests:
97+
@echo ""
98+
@echo "======================================================================"
99+
@echo "Phase 2: Running Integration Tests in Container"
100+
@echo "======================================================================"
101+
@echo ""
102+
@echo "Installing Go and running tests inside container..."
103+
$(CONTAINER_RUNTIME) run --rm \
104+
-v $(REPO_ROOT)/java-analyzer-bundle.test:/tests$(VOLUME_FLAGS) \
105+
-e WORKSPACE_DIR=/tests/projects \
106+
-e JDTLS_PATH=/jdtls \
107+
--workdir /tests/integration \
108+
--entrypoint /bin/sh \
109+
$(IMAGE_NAME) \
110+
-c "microdnf install -y golang && go mod download && go test -v"
111+
@echo ""
112+
@echo "✓ Integration tests passed"
113+
114+
# Clean targets
115+
clean: clean-go
116+
@echo "======================================================================"
117+
@echo "Cleaning Build Artifacts"
118+
@echo "======================================================================"
119+
mvn clean
120+
@echo ""
121+
@echo "✓ Maven artifacts cleaned"
122+
123+
clean-containers:
124+
@echo "======================================================================"
125+
@echo "Removing Container Images"
126+
@echo "======================================================================"
127+
-$(CONTAINER_RUNTIME) rmi $(IMAGE_NAME) 2>/dev/null || true
128+
@echo ""
129+
@echo "✓ Container images removed"
130+
131+
clean-go:
132+
@echo "Cleaning Go build artifacts..."
133+
cd $(GO_MODULE) && go clean -testcache
134+
@echo "✓ Go artifacts cleaned"
135+
136+
# Development targets
137+
.PHONY: test test-phase1 test-phase2 verify
138+
test: ci
139+
test-phase1: phase1
140+
test-phase2: phase2
141+
verify: ci

java-analyzer-bundle.core/src/main/java/io/konveyor/tackle/core/internal/SampleDelegateCommandHandler.java

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.eclipse.jdt.core.IJavaElement;
1818
import org.eclipse.jdt.core.IJavaProject;
1919
import org.eclipse.jdt.core.IPackageFragment;
20+
import org.eclipse.jdt.core.IPackageFragmentRoot;
2021
import org.eclipse.jdt.core.dom.AST;
2122
import org.eclipse.jdt.core.dom.ASTParser;
2223
import org.eclipse.jdt.core.dom.CompilationUnit;
@@ -28,9 +29,8 @@
2829
import org.eclipse.jdt.core.search.SearchPattern;
2930
import org.eclipse.jdt.internal.core.search.JavaSearchParticipant;
3031
import org.eclipse.jdt.ls.core.internal.IDelegateCommandHandler;
31-
import org.eclipse.jdt.core.IPackageFragmentRoot;
32-
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
3332
import org.eclipse.jdt.ls.core.internal.JDTUtils;
33+
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
3434
import org.eclipse.jdt.ls.core.internal.JobHelpers;
3535
import org.eclipse.jdt.ls.core.internal.ProjectUtils;
3636
import org.eclipse.jdt.ls.core.internal.ResourceUtils;
@@ -164,6 +164,8 @@ private static SearchPattern mapLocationToSearchPatternLocation(int location, St
164164
*/
165165
private static SearchPattern getPatternSingleQuery(int location, String query) throws Exception {
166166
var pattern = SearchPattern.R_PATTERN_MATCH;
167+
// Package searches (location 11) always use PATTERN_MATCH because Eclipse JDT
168+
// package matching is more flexible than exact matching
167169
if ((!query.contains("?") && !query.contains("*")) && (location != 11)) {
168170
logInfo("Using full match");
169171
pattern = SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE;
@@ -180,23 +182,36 @@ private static SearchPattern getPatternSingleQuery(int location, String query) t
180182
return SearchPattern.createPattern(query, IJavaSearchConstants.TYPE, IJavaSearchConstants.IMPLEMENTORS, pattern);
181183
case 7:
182184
case 9:
183-
return SearchPattern.createPattern(query, IJavaSearchConstants.TYPE, IJavaSearchConstants.REFERENCES, pattern);
185+
// Include R_ERASURE_MATCH to match parameterized types (e.g., List<String> when searching for java.util.List)
186+
return SearchPattern.createPattern(query, IJavaSearchConstants.TYPE, IJavaSearchConstants.REFERENCES, pattern | SearchPattern.R_ERASURE_MATCH);
184187
case 2:
185188
if (query.contains(".")) {
186189
return SearchPattern.createPattern(query, IJavaSearchConstants.METHOD, IJavaSearchConstants.QUALIFIED_REFERENCE, SearchPattern.R_PATTERN_MATCH | SearchPattern.R_ERASURE_MATCH);
187190
}
188191
// Switched back to referenced
189192
return SearchPattern.createPattern(query, IJavaSearchConstants.METHOD, IJavaSearchConstants.REFERENCES, SearchPattern.R_PATTERN_MATCH | SearchPattern.R_ERASURE_MATCH);
190193
case 3:
191-
return SearchPattern.createPattern(query, IJavaSearchConstants.CONSTRUCTOR, IJavaSearchConstants.ALL_OCCURRENCES, pattern);
194+
// Include R_ERASURE_MATCH to match parameterized constructor calls (e.g., ArrayList<String> when searching for java.util.ArrayList)
195+
return SearchPattern.createPattern(query, IJavaSearchConstants.CONSTRUCTOR, IJavaSearchConstants.ALL_OCCURRENCES, pattern | SearchPattern.R_ERASURE_MATCH);
192196
case 11:
193-
return SearchPattern.createPattern(query, IJavaSearchConstants.PACKAGE, IJavaSearchConstants.ALL_OCCURRENCES, pattern);
197+
// PACKAGE location should match any usage of a package:
198+
// - Package declarations (package io.konveyor.demo;)
199+
// - Import statements (import java.util.List; references java.util package)
200+
// - Fully qualified names (java.sql.Connection references java.sql package)
201+
// Create an OR pattern to find both declarations AND references
202+
SearchPattern declPattern = SearchPattern.createPattern(query, IJavaSearchConstants.PACKAGE, IJavaSearchConstants.DECLARATIONS, pattern);
203+
SearchPattern refPattern = SearchPattern.createPattern(query, IJavaSearchConstants.PACKAGE, IJavaSearchConstants.REFERENCES, pattern);
204+
return SearchPattern.createOrPattern(declPattern, refPattern);
194205
case 12:
195-
return SearchPattern.createPattern(query, IJavaSearchConstants.TYPE, IJavaSearchConstants.FIELD_DECLARATION_TYPE_REFERENCE, pattern);
206+
// Include R_ERASURE_MATCH to match parameterized field types (e.g., List<String> when searching for java.util.List)
207+
return SearchPattern.createPattern(query, IJavaSearchConstants.TYPE, IJavaSearchConstants.FIELD_DECLARATION_TYPE_REFERENCE, pattern | SearchPattern.R_ERASURE_MATCH);
196208
case 13:
197209
return SearchPattern.createPattern(query, IJavaSearchConstants.METHOD, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_EXACT_MATCH | SearchPattern.R_PATTERN_MATCH);
198210
case 14:
199211
return SearchPattern.createPattern(query, IJavaSearchConstants.CLASS, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_EXACT_MATCH | SearchPattern.R_PATTERN_MATCH);
212+
case 6:
213+
// Enum constants are fields, so we search for FIELD references
214+
return SearchPattern.createPattern(query, IJavaSearchConstants.FIELD, IJavaSearchConstants.ALL_OCCURRENCES, pattern);
200215
}
201216
throw new Exception("unable to create search pattern");
202217
}
@@ -345,7 +360,7 @@ protected static List<SymbolInformation> search(String projectName, ArrayList<St
345360

346361
SearchEngine searchEngine = new SearchEngine();
347362

348-
SymbolInformationTypeRequestor requestor = new SymbolInformationTypeRequestor(symbols, 0, monitor, location, query, annotationQuery);
363+
SymbolInformationTypeRequestor requestor = new SymbolInformationTypeRequestor(symbols, 0, monitor, location, query, annotationQuery, pattern);
349364

350365
//Use the default search participents
351366
SearchParticipant participent = new JavaSearchParticipant();
@@ -426,4 +441,4 @@ public static Location getLocationForImport(ICompilationUnit icu, ImportDeclarat
426441
return null;
427442
}
428443
}
429-
}
444+
}

0 commit comments

Comments
 (0)