-
Notifications
You must be signed in to change notification settings - Fork 503
feat: Add read-ahead configuration and verification support for integration tests #4777
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
base: master
Are you sure you want to change the base?
Changes from 21 commits
42d7a9f
65ad250
53250e2
d796168
970f287
7dd45a1
e08125d
64c8b89
c608202
803fb49
85888f4
775f3f3
ffad885
24824d1
19d1683
8f8d43b
9216b01
5112c58
7e2617d
266c835
594e6f9
5f9c31e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,219 @@ | ||||||||||||||||||||||
| #!/bin/bash | ||||||||||||||||||||||
| # Copyright 2026 Google LLC | ||||||||||||||||||||||
| # | ||||||||||||||||||||||
| # 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. | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Exit on error, treat unset variables as errors, and propagate pipeline errors. | ||||||||||||||||||||||
| # Note: We handle command failures manually for the main test runs to ensure both run. | ||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Logging Helpers | ||||||||||||||||||||||
| log_info() { | ||||||||||||||||||||||
| echo "[INFO] $(date +"%Y-%m-%d %H:%M:%S"): $1" | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| log_error() { | ||||||||||||||||||||||
| echo "[ERROR] $(date +"%Y-%m-%d %H:%M:%S"): $1" | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Defaults | ||||||||||||||||||||||
| LOCAL_RUN=false | ||||||||||||||||||||||
| RELEASE_PACKAGE_BUCKET="" | ||||||||||||||||||||||
| RELEASE_VERSION="" | ||||||||||||||||||||||
| RUN_TESTS_WITH_ZONAL_BUCKET=false | ||||||||||||||||||||||
| READ_AHEAD_KB="" | ||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The help message for To align the implementation with the documented default and ensure the verification test runs by default in the NPI conformance suite, initialize
Suggested change
|
||||||||||||||||||||||
| PROJECT_ID="" | ||||||||||||||||||||||
| BUCKET_LOCATION="" | ||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| usage() { | ||||||||||||||||||||||
| echo "Usage: $0 [options]" | ||||||||||||||||||||||
| echo "Options:" | ||||||||||||||||||||||
| echo " --local-run Pass this flag to run this script for local runs. If this flag is passed then gcsfuse is built" | ||||||||||||||||||||||
| echo " locally instead of getting installed by pre-built package from release bucket." | ||||||||||||||||||||||
| echo " --release-package-bucket <bkt> Name of the GCS bucket from which release packages will be fetched." | ||||||||||||||||||||||
| echo " Release package bucket is required if not running using --local-run" | ||||||||||||||||||||||
| echo " --release-version <3.0.0> Release version determines from which directory the pre-built package is used from release package bucket." | ||||||||||||||||||||||
| echo " Release version is required if not running using --local-run" | ||||||||||||||||||||||
| echo " --zonal Should run tests for zonal bucket (Default: false)" | ||||||||||||||||||||||
| echo " --read-ahead-kb <kb> The read-ahead size in KB to set on the FUSE mount point. If not specified, the kernel default is used. (Optional)" | ||||||||||||||||||||||
| echo " --project-id <project-id> Google Cloud Project ID. (Optional)" | ||||||||||||||||||||||
| echo " --bucket-location <location> Google Cloud Storage bucket location (e.g. 'us-central1'). (Optional)" | ||||||||||||||||||||||
| echo " --output-dir <output-dir> Directory in which all of log files generated by this script will be stored. (Default: /tmp)" | ||||||||||||||||||||||
| echo " --help Display this help and exit." | ||||||||||||||||||||||
| exit "$1" | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Define options for getopt | ||||||||||||||||||||||
| LONG=local-run,zonal,release-package-bucket:,release-version:,read-ahead-kb:,project-id:,bucket-location:,output-dir:,help | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Parse the options using getopt | ||||||||||||||||||||||
| if ! PARSED=$(getopt --options "" --longoptions "$LONG" --name "$0" -- "$@"); then | ||||||||||||||||||||||
| usage 1 | ||||||||||||||||||||||
| fi | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Output directory where all artifacts generated by this script will be stored. | ||||||||||||||||||||||
| OUTPUT_DIR="" | ||||||||||||||||||||||
| # Read the parsed options back into the positional parameters. | ||||||||||||||||||||||
| eval set -- "$PARSED" | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Loop through the options and assign values to our variables | ||||||||||||||||||||||
| while (( $# >= 1 )); do | ||||||||||||||||||||||
| case "$1" in | ||||||||||||||||||||||
| --release-version) | ||||||||||||||||||||||
| RELEASE_VERSION="$2" | ||||||||||||||||||||||
| shift 2 | ||||||||||||||||||||||
| RE="^[0-9]+\.[0-9]+\.[0-9]+$" | ||||||||||||||||||||||
| if [[ ! $RELEASE_VERSION =~ $RE ]]; then | ||||||||||||||||||||||
| log_error "--release-version value '$RELEASE_VERSION' is incorrectly formatted." | ||||||||||||||||||||||
| usage 1 | ||||||||||||||||||||||
| fi | ||||||||||||||||||||||
| ;; | ||||||||||||||||||||||
| --release-package-bucket) | ||||||||||||||||||||||
| RELEASE_PACKAGE_BUCKET="$2" | ||||||||||||||||||||||
| shift 2 | ||||||||||||||||||||||
| ;; | ||||||||||||||||||||||
| --zonal) | ||||||||||||||||||||||
| RUN_TESTS_WITH_ZONAL_BUCKET=true | ||||||||||||||||||||||
| shift | ||||||||||||||||||||||
| ;; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| --read-ahead-kb) | ||||||||||||||||||||||
| READ_AHEAD_KB="$2" | ||||||||||||||||||||||
| shift 2 | ||||||||||||||||||||||
| ;; | ||||||||||||||||||||||
| --project-id) | ||||||||||||||||||||||
| PROJECT_ID="$2" | ||||||||||||||||||||||
| shift 2 | ||||||||||||||||||||||
| ;; | ||||||||||||||||||||||
| --bucket-location) | ||||||||||||||||||||||
| BUCKET_LOCATION="$2" | ||||||||||||||||||||||
| shift 2 | ||||||||||||||||||||||
| ;; | ||||||||||||||||||||||
| --output-dir) | ||||||||||||||||||||||
| OUTPUT_DIR="$2" | ||||||||||||||||||||||
| shift 2 | ||||||||||||||||||||||
| ;; | ||||||||||||||||||||||
| --local-run) | ||||||||||||||||||||||
| LOCAL_RUN=true | ||||||||||||||||||||||
| shift | ||||||||||||||||||||||
| ;; | ||||||||||||||||||||||
| --help) | ||||||||||||||||||||||
| usage 0 | ||||||||||||||||||||||
| ;; | ||||||||||||||||||||||
| --) | ||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||||
| shift | ||||||||||||||||||||||
| break | ||||||||||||||||||||||
| ;; | ||||||||||||||||||||||
| *) | ||||||||||||||||||||||
| log_error "Unrecognized arguments [$*]." | ||||||||||||||||||||||
| usage 1 | ||||||||||||||||||||||
| ;; | ||||||||||||||||||||||
| esac | ||||||||||||||||||||||
| done | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Argument validation | ||||||||||||||||||||||
| if [[ "$LOCAL_RUN" == "false" ]]; then | ||||||||||||||||||||||
| if [[ -z "$RELEASE_VERSION" ]]; then | ||||||||||||||||||||||
| log_error "--release-version required if not running with --local-run" | ||||||||||||||||||||||
| usage 1 | ||||||||||||||||||||||
| fi | ||||||||||||||||||||||
| if [[ -z "$RELEASE_PACKAGE_BUCKET" ]]; then | ||||||||||||||||||||||
| log_error "--release-package-bucket required if not running with --local-run" | ||||||||||||||||||||||
| usage 1 | ||||||||||||||||||||||
| fi | ||||||||||||||||||||||
| fi | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Build args for the e2e script | ||||||||||||||||||||||
| ARGS=() | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Local Run Validation and gcsfuse package installation. | ||||||||||||||||||||||
| if ${LOCAL_RUN}; then | ||||||||||||||||||||||
| log_info "Running script in local mode, gcsfuse binary will be built from current repository." | ||||||||||||||||||||||
| else | ||||||||||||||||||||||
| log_info "Running script with release version package from release bucket for version $RELEASE_VERSION will be installed." | ||||||||||||||||||||||
| # Identify the OS and Architecture | ||||||||||||||||||||||
| if [ -f /etc/os-release ]; then | ||||||||||||||||||||||
| DISTRO_DATA=$( (source /etc/os-release; echo "${ID:-} ${ID_LIKE:-}") ) | ||||||||||||||||||||||
| if [[ "$DISTRO_DATA" == *"debian"* ]] || [[ "$DISTRO_DATA" == *"ubuntu"* ]]; then | ||||||||||||||||||||||
| ARCH=$(dpkg --print-architecture) | ||||||||||||||||||||||
| ARGS+=( | ||||||||||||||||||||||
| "--install-package-from-path=gs://${RELEASE_PACKAGE_BUCKET}/v${RELEASE_VERSION}/gcsfuse_${RELEASE_VERSION}_${ARCH}.deb" | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
| elif [[ "$DISTRO_DATA" == *"rhel"* ]] || [[ "$DISTRO_DATA" == *"centos"* ]]; then | ||||||||||||||||||||||
| ARCH=$(uname -m) | ||||||||||||||||||||||
| ARGS+=( | ||||||||||||||||||||||
| "--install-package-from-path=gs://${RELEASE_PACKAGE_BUCKET}/v${RELEASE_VERSION}/gcsfuse-${RELEASE_VERSION}-1.${ARCH}.rpm" | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
| else | ||||||||||||||||||||||
| log_error "This script only supports Debian/Ubuntu/rhel/centos based distributions." | ||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||
| fi | ||||||||||||||||||||||
| else | ||||||||||||||||||||||
| log_error "/etc/os-release not found. Unable to determine distribution" | ||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||
| fi | ||||||||||||||||||||||
| fi | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Set parallelism to 4 as it is optimal for all of the release VM(s). | ||||||||||||||||||||||
| ARGS+=("--package-level-parallelism=4") | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Set --zonal arg if required | ||||||||||||||||||||||
| if ${RUN_TESTS_WITH_ZONAL_BUCKET}; then | ||||||||||||||||||||||
| log_info "Running zonal NPI conformance tests." | ||||||||||||||||||||||
| ARGS+=("--zonal") | ||||||||||||||||||||||
| else | ||||||||||||||||||||||
| log_info "Running regional NPI conformance tests." | ||||||||||||||||||||||
| fi | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Fallback to /tmp if OUTPUT_DIR is unset | ||||||||||||||||||||||
| OUTPUT_DIR="${OUTPUT_DIR:-/tmp}" | ||||||||||||||||||||||
| mkdir -p "$OUTPUT_DIR" || { | ||||||||||||||||||||||
| log_error "Failed to create or access output directory '$OUTPUT_DIR'"; | ||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| ARGS+=("--output-dir=$OUTPUT_DIR") | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Set --flake-attempts to 3 for NPI conformance tests. | ||||||||||||||||||||||
| ARGS+=("--flake-attempts=3") | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Pass project-id if provided | ||||||||||||||||||||||
| if [[ -n "$PROJECT_ID" ]]; then | ||||||||||||||||||||||
| ARGS+=("--project-id=$PROJECT_ID") | ||||||||||||||||||||||
| fi | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Pass bucket-location if provided | ||||||||||||||||||||||
| if [[ -n "$BUCKET_LOCATION" ]]; then | ||||||||||||||||||||||
| ARGS+=("--bucket-location=$BUCKET_LOCATION") | ||||||||||||||||||||||
| fi | ||||||||||||||||||||||
|
Comment on lines
+195
to
+197
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Forward the
Suggested change
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Pass read-ahead-kb if explicitly provided, otherwise default to kernel default | ||||||||||||||||||||||
| if [[ -n "$READ_AHEAD_KB" ]]; then | ||||||||||||||||||||||
| ARGS+=("--read-ahead-kb=$READ_AHEAD_KB") | ||||||||||||||||||||||
| fi | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Configure NPI packages to run | ||||||||||||||||||||||
| ARGS+=( | ||||||||||||||||||||||
| "--skip-emulator" | ||||||||||||||||||||||
| "--run-package=concurrent_operations|kernel_list_cache|list_large_dir|dentry_cache|read_cache|local_file|operations" | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| log_info "==========================================================================" | ||||||||||||||||||||||
| log_info "🚀 Running NPI Conformance Suite..." | ||||||||||||||||||||||
| log_info "==========================================================================" | ||||||||||||||||||||||
| if ! bash ./tools/integration_tests/improved_run_e2e_tests.sh "${ARGS[@]}"; then | ||||||||||||||||||||||
| log_error "NPI Conformance Suite failed." | ||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||
| else | ||||||||||||||||||||||
| log_info "NPI Conformance Suite completed successfully!" | ||||||||||||||||||||||
| fi | ||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| // Copyright 2026 Google LLC | ||
| // | ||
| // 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 operations_test | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/googlecloudplatform/gcsfuse/v3/tools/integration_tests/util/mounting" | ||
| "github.com/googlecloudplatform/gcsfuse/v3/tools/integration_tests/util/setup" | ||
| ) | ||
|
|
||
| func TestVerifyReadAheadKB(t *testing.T) { | ||
| expectedKB := setup.ReadAheadKB() | ||
| if expectedKB <= 0 { | ||
| t.Skip("Skipping read-ahead verification as read-ahead-kb is not configured.") | ||
| } | ||
|
|
||
| err := mounting.VerifyReadAhead(setup.RootMntDir(), expectedKB) | ||
| if err != nil { | ||
| t.Errorf("read-ahead verification failed: %v", err) | ||
| } | ||
|
kislaykishore marked this conversation as resolved.
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -55,5 +55,13 @@ func MountGcsfuse(binaryFile string, flags []string) error { | |
| log.Println("Error: ", string(output)) | ||
| return fmt.Errorf("cannot mount gcsfuse: %w\n", err) | ||
| } | ||
|
|
||
| readAheadKB := setup.ReadAheadKB() | ||
| if readAheadKB > 0 { | ||
| if err := ConfigureReadAhead(setup.RootMntDir(), readAheadKB); err != nil { | ||
| return fmt.Errorf("failed to configure read-ahead: %w", err) | ||
| } | ||
| } | ||
|
Comment on lines
+59
to
+64
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In integration tests, GCSFuse might be mounted to a custom directory passed via readAheadKB := setup.ReadAheadKB()
if readAheadKB > 0 {
mountDir := setup.RootMntDir()
if len(flags) > 0 {
lastArg := flags[len(flags)-1]
if fi, err := os.Stat(lastArg); err == nil && fi.IsDir() {
mountDir = lastArg
}
}
if err := ConfigureReadAhead(mountDir, readAheadKB); err != nil {
return fmt.Errorf("failed to configure read-ahead: %w", err)
}
} |
||
|
|
||
| return nil | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of using
$(eval ...)inside the recipe, define the default value forREAD_AHEAD_KBat the top of the Makefile alongside other variable definitions (e.g.,CSI_VERSION ?= main). This is more idiomatic and avoids mixing Make evaluation with shell execution.