This is an automated email from the ASF dual-hosted git repository.

adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 9aa41fdbaf HDDS-12574. Add script to find modules by test classes 
(#8062)
9aa41fdbaf is described below

commit 9aa41fdbaf90b801bc6eafffc1a4ce45b27bcf83
Author: Peter Lee <[email protected]>
AuthorDate: Thu Mar 13 23:05:02 2025 +0800

    HDDS-12574. Add script to find modules by test classes (#8062)
---
 dev-support/ci/find_test_class_project.bats | 239 ++++++++++++++++++++++++++++
 dev-support/ci/find_test_class_project.sh   |  98 ++++++++++++
 dev-support/ci/selective_ci_checks.sh       |   2 +
 hadoop-ozone/dev-support/checks/bats.sh     |   1 +
 4 files changed, 340 insertions(+)

diff --git a/dev-support/ci/find_test_class_project.bats 
b/dev-support/ci/find_test_class_project.bats
new file mode 100644
index 0000000000..40be1fbfbb
--- /dev/null
+++ b/dev-support/ci/find_test_class_project.bats
@@ -0,0 +1,239 @@
+#!/usr/bin/env bats
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+load find_test_class_project.sh
+
+setup() {
+  # Create a temporary directory for test files
+  TEST_DIR=$(mktemp -d)
+  mkdir -p "${TEST_DIR}/project1/src/test/java/org/apache/ozone/test"
+  mkdir -p "${TEST_DIR}/project2/src/test/java/org/apache/ozone/test"  
+  touch "${TEST_DIR}/project1/pom.xml"
+  touch "${TEST_DIR}/project2/pom.xml"
+  touch 
"${TEST_DIR}/project1/src/test/java/org/apache/ozone/test/TestClass1.java"
+  touch 
"${TEST_DIR}/project2/src/test/java/org/apache/ozone/test/TestClass2.java"
+  
+  ORIG_DIR=$(pwd)
+  cd "${TEST_DIR}"
+}
+
+teardown() {
+  cd "${ORIG_DIR}"
+  rm -rf "${TEST_DIR}"
+}
+
+# Test the find_project_paths_for_test_class function
+
+@test "find project for simple class name" {
+  result=$(find_project_paths_for_test_class "TestClass1" 2>/dev/null)
+
+  [ "$result" = "./project1" ]
+}
+
+@test "find project for class with package" {
+  result=$(find_project_paths_for_test_class 
"org.apache.ozone.test.TestClass2" 2>/dev/null)
+
+  [ "$result" = "./project2" ]
+}
+
+@test "find project for wildcard class" {
+  result=$(find_project_paths_for_test_class "TestClass*" 2>/dev/null)
+  expected=$(echo -e "./project1\n./project2")
+
+  [ "$result" = "$expected" ]
+}
+
+@test "no project for non-existent class" {
+  result=$(find_project_paths_for_test_class "NonExistentClass" 2>/dev/null)
+
+  [ -z "$result" ]
+}
+
+@test "skip abstract classes" {
+  touch 
"${TEST_DIR}/project1/src/test/java/org/apache/ozone/test/AbstractTestClass.java"
+  
+  result=$(find_project_paths_for_test_class "AbstractTestClass" 2>/dev/null)
+  
+  [ -z "$result" ]
+}
+
+@test "empty class name returns nothing" {
+  result=$(find_project_paths_for_test_class "" 2>/dev/null)
+  
+  [ -z "$result" ]
+}
+
+@test "multiple projects with same test class name" {
+  touch 
"${TEST_DIR}/project1/src/test/java/org/apache/ozone/test/CommonTest.java"
+  touch 
"${TEST_DIR}/project2/src/test/java/org/apache/ozone/test/CommonTest.java"
+  
+  result=$(find_project_paths_for_test_class "CommonTest" 2>/dev/null)
+  
+  expected=$(echo -e "./project1\n./project2")
+  [ "$result" = "$expected" ]
+}
+
+@test "project without pom.xml is ignored" {
+  mkdir -p "${TEST_DIR}/project3/src/test/java/org/apache/ozone/test"
+  touch 
"${TEST_DIR}/project3/src/test/java/org/apache/ozone/test/TestClass3.java"
+  
+  result=$(find_project_paths_for_test_class "TestClass3" 2>/dev/null)
+  
+  [ -z "$result" ]
+}
+
+@test "partial package name search" {
+  result=$(find_project_paths_for_test_class "ozone.test.TestClass2" 
2>/dev/null)
+  
+  [ "$result" = "./project2" ]
+}
+
+@test "test class in non-standard test directory" {
+  mkdir -p "${TEST_DIR}/project1/src/test/scala/org/apache/ozone/test"
+  touch 
"${TEST_DIR}/project1/src/test/scala/org/apache/ozone/test/ScalaTest.java"
+  
+  result=$(find_project_paths_for_test_class "ScalaTest" 2>/dev/null)
+  
+  [ "$result" = "./project1" ]
+}
+
+@test "case sensitivity in class name" {
+  touch 
"${TEST_DIR}/project1/src/test/java/org/apache/ozone/test/MixedCaseTest.java"
+  
+  result=$(find_project_paths_for_test_class "mixedcasetest" 2>/dev/null)
+
+  [ -z "$result" ]
+}
+
+@test "nested project structure" {
+  mkdir -p "${TEST_DIR}/parent/child/src/test/java/org/apache/ozone/test"
+  touch "${TEST_DIR}/parent/child/pom.xml"
+  touch 
"${TEST_DIR}/parent/child/src/test/java/org/apache/ozone/test/NestedTest.java"
+  
+  result=$(find_project_paths_for_test_class "NestedTest" 2>/dev/null)
+  
+  [ "$result" = "./parent/child" ]
+}
+
+@test "test class with numeric suffix" {
+  touch "${TEST_DIR}/project1/src/test/java/org/apache/ozone/test/Test1.java"
+  touch "${TEST_DIR}/project1/src/test/java/org/apache/ozone/test/Test2.java"
+  touch "${TEST_DIR}/project2/src/test/java/org/apache/ozone/test/Test3.java"
+  
+  result=$(find_project_paths_for_test_class "Test[1-2]" 2>/dev/null)
+  
+  [ "$result" = "./project1" ]
+}
+
+@test "multiple test classes matching pattern" {
+  touch "${TEST_DIR}/project1/src/test/java/org/apache/ozone/test/TestA.java"
+  touch "${TEST_DIR}/project2/src/test/java/org/apache/ozone/test/TestB.java"
+  touch "${TEST_DIR}/project2/src/test/java/org/apache/ozone/test/TestC.java"
+  
+  result=$(find_project_paths_for_test_class "Test[A-C]" 2>/dev/null)
+  
+  expected=$(echo -e "./project1\n./project2")
+  [ "$result" = "$expected" ]
+}
+
+@test "test class in multiple package levels" {
+  mkdir -p 
"${TEST_DIR}/project1/src/test/java/org/apache/ozone/test/deep/nested/pkg"
+  touch 
"${TEST_DIR}/project1/src/test/java/org/apache/ozone/test/deep/nested/pkg/DeepTest.java"
+  
+  result=$(find_project_paths_for_test_class 
"org.apache.ozone.test.deep.nested.pkg.DeepTest" 2>/dev/null)
+  
+  [ "$result" = "./project1" ]
+}
+
+@test "test class with same name in different packages" {
+  mkdir -p "${TEST_DIR}/project1/src/test/java/org/apache/ozone/test/pkg1"
+  mkdir -p "${TEST_DIR}/project2/src/test/java/org/apache/ozone/test/pkg2"
+  touch 
"${TEST_DIR}/project1/src/test/java/org/apache/ozone/test/pkg1/SameNameTest.java"
+  touch 
"${TEST_DIR}/project2/src/test/java/org/apache/ozone/test/pkg2/SameNameTest.java"
+  
+  result=$(find_project_paths_for_test_class "SameNameTest" 2>/dev/null)
+  
+  expected=$(echo -e "./project1\n./project2")
+  [ "$result" = "$expected" ]
+}
+
+@test "test class with package wildcard" {
+  mkdir -p "${TEST_DIR}/project1/src/test/java/org/apache/ozone/test/pkg1"
+  mkdir -p "${TEST_DIR}/project2/src/test/java/org/apache/ozone/test/pkg2"
+  touch 
"${TEST_DIR}/project1/src/test/java/org/apache/ozone/test/pkg1/WildcardTest.java"
+  touch 
"${TEST_DIR}/project2/src/test/java/org/apache/ozone/test/pkg2/WildcardTest.java"
+  
+  result=$(find_project_paths_for_test_class 
"org.apache.ozone.test.pkg*.WildcardTest" 2>/dev/null)
+  
+  expected=$(echo -e "./project1\n./project2")
+  [ "$result" = "$expected" ]
+}
+
+@test "test class with exact package match" {
+  mkdir -p "${TEST_DIR}/project1/src/test/java/org/apache/ozone/test/exact"
+  mkdir -p 
"${TEST_DIR}/project1/src/test/java/org/apache/ozone/test/exactmatch"
+  touch 
"${TEST_DIR}/project1/src/test/java/org/apache/ozone/test/exact/ExactTest.java"
+  touch 
"${TEST_DIR}/project1/src/test/java/org/apache/ozone/test/exactmatch/ExactTest.java"
+  result=$(find_project_paths_for_test_class 
"org.apache.ozone.test.exact.ExactTest" 2>/dev/null)
+  
+  [ "$result" = "./project1" ]
+}
+
+@test "test class with trailing whitespace" {
+  result=$(find_project_paths_for_test_class "TestClass1 " 2>/dev/null)
+  
+  [ "$result" = "./project1" ]
+}
+
+@test "test class project with trailing whitespace" {
+  result=$(find_project_paths_for_test_class "apache.ozone.test.TestClass1 " 
2>/dev/null)
+
+  [ "$result" = "./project1" ]
+}
+
+@test "test class with leading whitespace" {
+  result=$(find_project_paths_for_test_class " TestClass1" 2>/dev/null)
+
+  [ "$result" = "./project1" ]
+}
+
+@test "test class with partial package and wildcard" {
+  result=$(find_project_paths_for_test_class "apache.*.TestClass*" 2>/dev/null)
+
+  expected=$(echo -e "./project1\n./project2")
+  [ "$result" = "$expected" ]
+}
+
+# Test the build_maven_project_list function
+
+@test "build maven project list with empty project paths" {
+  result=$(build_maven_project_list "")
+  
+  [ "$result" = "" ]
+}
+
+@test "build maven project list with one project path" {
+  result=$(build_maven_project_list "./project1")
+
+  [ "$result" = "-pl ./project1" ]
+}
+
+@test "build maven project list with multiple project paths" {
+  local project_paths=$(echo -e "./project1\n./project2")
+  result=$(build_maven_project_list "$project_paths")
+
+  [ "$result" = "-pl ./project1,./project2" ]
+}
diff --git a/dev-support/ci/find_test_class_project.sh 
b/dev-support/ci/find_test_class_project.sh
new file mode 100755
index 0000000000..6f6e755984
--- /dev/null
+++ b/dev-support/ci/find_test_class_project.sh
@@ -0,0 +1,98 @@
+#!/usr/bin/env bash
+
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+# Function to find project paths for a given test class
+find_project_paths_for_test_class() {
+  local test_class="$1"
+
+  if [[ -z "${test_class}" ]] || [[ "${test_class}" == "Abstract"* ]]; then
+    return
+  fi
+
+  echo "Finding project for test class: ${test_class}" >&2
+
+  # Trim test_class of whitespace
+  local base_class_name=$(echo "${test_class}" | xargs)
+
+  # If the base name is empty after removing wildcards, use a reasonable 
default
+  if [[ -z "${base_class_name}" ]]; then
+    echo "Test class name contains only wildcards, searching in all test 
directories" >&2
+    return
+  fi
+
+  echo "Searching for files matching base name: ${base_class_name}" >&2
+
+  # Find all projects containing matching test classes - use a more flexible 
search approach
+  # First try direct filename search
+  local test_files=($(find . -path "*/src/test/*" -name 
"${base_class_name}.java" | sort -u))
+
+  # If no files found and the class name contains dots (package notation), try 
searching by path
+  if [[ ${#test_files[@]} -eq 0 && "${base_class_name}" == *"."* ]]; then
+    # Convert base class to path format
+    local test_class_path="${base_class_name//./\/}.java"
+    echo "No files found with direct name search, trying path-based search" >&2
+    echo "TEST_CLASS_PATH pattern: ${test_class_path}" >&2
+
+    # Search by path pattern
+    test_files=($(find . -path "*/src/test/*/${test_class_path%.*}*.java" | 
sort -u))
+  fi
+
+  echo "Found ${#test_files[@]} matching test file(s)" >&2
+
+  if [[ ${#test_files[@]} -gt 0 ]]; then
+    # Extract project paths (up to the src/test directory)
+    local project_paths=()
+    for test_file in "${test_files[@]}"; do
+      echo "TEST_FILE: ${test_file}" >&2
+      local project_path=$(dirname "${test_file}" | sed -e 's|/src/test.*||')
+      if [[ -f "${project_path}/pom.xml" ]]; then
+        echo "Found test in project: ${project_path}" >&2
+        project_paths+=("${project_path}")
+      fi
+    done
+
+    printf '%s\n' "${project_paths[@]}" | sort -u
+  else
+    echo "Could not find project for test class pattern: ${test_class}" >&2
+  fi
+}
+
+# Takes a project list which is the output of 
`find_project_paths_for_test_class`
+# and returns a string that can use for maven -pl option, eg. 
"./project1\n./project2" -> "-pl ./project1,./project2"
+build_maven_project_list() {
+  local project_paths="$1"
+  if [[ -z "${project_paths}" ]]; then
+    echo ""
+    return
+  fi
+
+  local comma_separated=$(echo "${project_paths}" | tr '\n' ',')
+  comma_separated="${comma_separated%,}"
+  echo "-pl ${comma_separated}"
+}
+
+# If option get-pl set, write the maven -pl option value to stdout
+# otherwise, write the project paths to stdout
+if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
+  if [[ "$1" == "--get-pl" ]]; then
+    shift
+    project_paths=$(find_project_paths_for_test_class "$@")
+    build_maven_project_list "${project_paths}"
+  else
+    find_project_paths_for_test_class "$@"
+  fi
+fi
diff --git a/dev-support/ci/selective_ci_checks.sh 
b/dev-support/ci/selective_ci_checks.sh
index 1017f354eb..24577653d6 100755
--- a/dev-support/ci/selective_ci_checks.sh
+++ b/dev-support/ci/selective_ci_checks.sh
@@ -199,6 +199,7 @@ function run_all_tests_if_environment_files_changed() {
     )
     local ignore_array=(
         "^dev-support/ci/pr_title_check"
+        "^dev-support/ci/find_test_class_project"
     )
     filter_changed_files
 
@@ -478,6 +479,7 @@ function get_count_misc_files() {
     start_end::group_start "Count misc. files"
     local pattern_array=(
         "^dev-support/ci/pr_title_check"
+        "^dev-support/ci/find_test_class_project"
         "^.github"
         "^hadoop-hdds/dev-support/checkstyle"
         "^hadoop-ozone/dev-support/checks"
diff --git a/hadoop-ozone/dev-support/checks/bats.sh 
b/hadoop-ozone/dev-support/checks/bats.sh
index 3dec6052a9..49d5cb0912 100755
--- a/hadoop-ozone/dev-support/checks/bats.sh
+++ b/hadoop-ozone/dev-support/checks/bats.sh
@@ -34,6 +34,7 @@ find * \( \
     -path '*/src/test/shell/*' -name '*.bats' \
     -or -path dev-support/ci/selective_ci_checks.bats \
     -or -path dev-support/ci/pr_title_check.bats \
+    -or -path dev-support/ci/find_test_class_project.bats \
     \) -print0 \
   | xargs -0 -n1 bats --formatter tap \
   | tee -a "${REPORT_DIR}/output.log"


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to