Skip to content

test(filter) : Migrate Filter test and Improve code coverage#5638

Open
yuvraj-kolkar17 wants to merge 2 commits intofluid-cloudnative:masterfrom
yuvraj-kolkar17:test/filter-migrate-test
Open

test(filter) : Migrate Filter test and Improve code coverage#5638
yuvraj-kolkar17 wants to merge 2 commits intofluid-cloudnative:masterfrom
yuvraj-kolkar17:test/filter-migrate-test

Conversation

@yuvraj-kolkar17
Copy link
Contributor

Ⅰ. Describe what this PR does

Migrated your test from testify to Ginkgo + Gomega. Key changes:

  1. Test Suite Setup: Added TestSecurity function with RegisterFailHandler(Fail) and RunSpecs to initialize the Ginkgo test suite
  2. Test Structure: Converted table-driven tests to Ginkgo's Describe/Context/It blocks
  3. Assertions: Replaced reflect.DeepEqual and t.Errorf with Gomega's Expect().To(Equal()) matcher
  4. Imports: Added Ginkgo v2 and Gomega imports with dot notation for cleaner syntax
  5. Organization: Grouped related tests under descriptive contexts

Ⅱ. Does this pull request fix one issue?

Part of #5407

Ⅲ. List the added test cases (unit test/integration test) if any, please explain if no tests are needed.

Ⅳ. Describe how to verify it

image

Ⅴ. Special notes for reviews

Signed-off-by: Yuvraj Kolkar <kolkaryuvraj2@gmail.com>
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @yuvraj-kolkar17, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly refactors the testing infrastructure for the pkg/utils/security package. By migrating from the standard Go testing framework to Ginkgo and Gomega, the tests become more expressive, organized, and maintainable. This change enhances the quality and reliability of the security utility functions, particularly those related to command filtering and sensitive key handling, and also improves the visibility of code coverage.

Highlights

  • Test Framework Migration: Migrated existing tests for the security package's filter functionality from standard Go testing to Ginkgo and Gomega.
  • Test Suite Setup Refactoring: Refactored test suite setup by introducing TestSecurity with RegisterFailHandler(Fail) and RunSpecs for Ginkgo initialization.
  • Improved Test Structure: Converted table-driven test cases into structured Describe, Context, and It blocks for improved readability and organization.
  • Enhanced Assertions: Replaced reflect.DeepEqual and t.Errorf assertions with Gomega's Expect().To(Equal()) matchers.
  • Dependency Updates: Updated Go imports to include Ginkgo v2 and Gomega, utilizing dot notation for cleaner syntax.
  • Code Coverage Reporting: Added a coverage.html file, indicating improved code coverage reporting for the security package.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@fluid-e2e-bot
Copy link

fluid-e2e-bot bot commented Jan 30, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign yangyuliufeng for approval by writing /assign @yangyuliufeng in a comment. For more information see:The Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@fluid-e2e-bot
Copy link

fluid-e2e-bot bot commented Jan 30, 2026

Hi @yuvraj-kolkar17. Thanks for your PR.

I'm waiting for a fluid-cloudnative member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request successfully migrates the tests for the filter package from testify to Ginkgo and Gomega, which improves the structure and readability of the tests. The increased code coverage to 100% is also a great achievement.

I have provided two review comments on the test file. One suggests a way to improve test isolation and prevent future flakiness. The other points out a missing edge case in the tests which reveals a bug in the implementation, and I've suggested a new test case to cover it.

Additionally, please consider if the generated coverage.html file should be committed to the repository. It's common practice to add such generated files to .gitignore to keep the repository clean.

expect := []string{"mount", "fs", "alluxio.underfs.s3.inherit.acl=false", "aws.secretKey=[ redacted ]"}
got := FilterCommand(input)
Expect(got).To(Equal(expect))
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

While the test coverage is 100%, there's an edge case not covered: when a single string contains multiple sensitive keys. The current implementation of FilterString appears to only handle one sensitive key per string, and it replaces the entire string. This can lead to incomplete redaction and non-deterministic behavior depending on map iteration order.

I suggest adding a new test case to cover this scenario. This test will likely fail, which will highlight the bug in FilterString that needs to be addressed.

		})

		It("should redact multiple sensitive keys in a single string", func() {
			input := []string{"aws.secretKey=secret and aws.accessKeyId=key"}
			// This test will fail with the current implementation, which only redacts one key
			// and replaces the entire string. A correct implementation should handle this.
			expect := []string{"aws.secretKey=[ redacted ] and aws.accessKeyId=[ redacted ]"}
			got := FilterCommand(input)
			Expect(got).To(Equal(expect))
		})

Comment on lines 55 to 75
var _ = Describe("FilterCommandWithSensitive", func() {
Context("when updating sensitive keys", func() {
It("should not redact keys that are not added as sensitive", func() {
filterKey := "test"
input := []string{"mount", "fs", "fs.azure.account.key=xxxxxxxxx"}
expect := []string{"mount", "fs", "fs.azure.account.key=xxxxxxxxx"}
UpdateSensitiveKey(filterKey)
got := FilterCommand(input)
Expect(got).To(Equal(expect))
})

}
It("should redact keys that are added as sensitive", func() {
filterKey := "fs.azure.account.key"
input := []string{"mount", "fs", "fs.azure.account.key=false"}
expect := []string{"mount", "fs", "fs.azure.account.key=[ redacted ]"}
UpdateSensitiveKey(filterKey)
got := FilterCommand(input)
Expect(got).To(Equal(expect))
})
})
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

These tests modify the global sensitiveKeys map, which can lead to flaky tests as they are not isolated. A test modifying this global state can affect the outcome of other tests, especially if they are run in parallel or a different order in the future.

To ensure test isolation, it's a best practice to reset the state before each test. You can use a BeforeEach block to reset the sensitiveKeys map to its initial state.

var _ = Describe("FilterCommandWithSensitive", func() {
	BeforeEach(func() {
		// Reset sensitiveKeys to its initial state before each test
		sensitiveKeys = map[string]bool{
			"aws.secretKey":          true,
			"aws.accessKeyId":        true,
			"fs.oss.accessKeyId":     true,
			"fs.oss.accessKeySecret": true,
		}
	})

	Context("when updating sensitive keys", func() {
		It("should not redact keys that are not added as sensitive", func() {
			filterKey := "test"
			input := []string{"mount", "fs", "fs.azure.account.key=xxxxxxxxx"}
			expect := []string{"mount", "fs", "fs.azure.account.key=xxxxxxxxx"}
			UpdateSensitiveKey(filterKey)
			got := FilterCommand(input)
			Expect(got).To(Equal(expect))
		})

		It("should redact keys that are added as sensitive", func() {
			filterKey := "fs.azure.account.key"
			input := []string{"mount", "fs", "fs.azure.account.key=false"}
			expect := []string{"mount", "fs", "fs.azure.account.key=[ redacted ]"}
			UpdateSensitiveKey(filterKey)
			got := FilterCommand(input)
			Expect(got).To(Equal(expect))
		})
	})
})

@yuvraj-kolkar17 yuvraj-kolkar17 force-pushed the test/filter-migrate-test branch from 18b7728 to 7ac901a Compare January 30, 2026 14:47
Signed-off-by: Yuvraj Kolkar <kolkaryuvraj2@gmail.com>
@sonarqubecloud
Copy link

@codecov
Copy link

codecov bot commented Jan 30, 2026

Codecov Report

❌ Patch coverage is 87.50000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 59.24%. Comparing base (6dd9555) to head (17cb7d3).
⚠️ Report is 54 commits behind head on master.

Files with missing lines Patch % Lines
pkg/utils/security/filter.go 87.50% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5638      +/-   ##
==========================================
+ Coverage   56.76%   59.24%   +2.48%     
==========================================
  Files         443      444       +1     
  Lines       30735    30559     -176     
==========================================
+ Hits        17447    18105     +658     
+ Misses      11734    10954     -780     
+ Partials     1554     1500      -54     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request successfully migrates the filter tests to Ginkgo and Gomega and improves the secret filtering logic. The test changes are well-structured. I have a few suggestions to improve the implementation further:

  • The new filtering logic in FilterString is a bit complex. I've suggested a refactoring to use regular expressions, which would make the code simpler and more maintainable.
  • There is a potential data race on the global sensitiveKeys map, which I've highlighted with a suggestion to use sync.RWMutex.
  • The code coverage report coverage.html has been committed. This type of generated file should typically be excluded from the repository.

Overall, good work on improving the tests and functionality.

@@ -34,14 +34,37 @@ func FilterCommand(command []string) (filteredCommand []string) {
}

func FilterString(line string) string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

There is a potential data race issue. The global variable sensitiveKeys is read in this function and modified in UpdateSensitiveKey without any synchronization. If these functions are called concurrently from different goroutines, it can lead to a crash or unpredictable behavior.

To fix this, you should use a sync.RWMutex to protect all accesses to sensitiveKeys.

For example:

import "sync"

var (
    sensitiveKeysMutex sync.RWMutex
    sensitiveKeys = map[string]bool{...}
)

// In FilterString
sensitiveKeysMutex.RLock()
defer sensitiveKeysMutex.RUnlock()
// ...

// In UpdateSensitiveKey
sensitiveKeysMutex.Lock()
defer sensitiveKeysMutex.Unlock()
// ...

Comment on lines +37 to +67
result := line
for s := range sensitiveKeys {
// if the log line contains a secret value redact it
if strings.Contains(line, s) {
line = s + "=[ redacted ]"
// if the log line contains a secret key, redact its value
if strings.Contains(result, s) {
// Look for pattern "key=" and replace everything after = until space or end
searchPattern := s + "="
idx := strings.Index(result, searchPattern)

for idx != -1 {
// Find the end of the value (next space or end of string)
startValue := idx + len(searchPattern)
endValue := startValue

// Find where the value ends (space, newline, or end of string)
for endValue < len(result) && result[endValue] != ' ' && result[endValue] != '\n' && result[endValue] != '\t' {
endValue++
}

// Replace the value with [ redacted ]
result = result[:startValue] + "[ redacted ]" + result[endValue:]

// Look for next occurrence
idx = strings.Index(result[startValue+len("[ redacted ]"):], searchPattern)
if idx != -1 {
idx = idx + startValue + len("[ redacted ]")
}
}
}
}

return line
return result
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current implementation for redacting sensitive values is functionally correct but quite complex, involving manual string searching and replacement in a loop. This makes the code hard to read and maintain.

A much simpler and more robust solution can be achieved using a single regular expression. This would also be more efficient as it processes the string in a single pass. You will need to add regexp to the file imports.

	var patterns []string
	for s := range sensitiveKeys {
		patterns = append(patterns, regexp.QuoteMeta(s))
	}

	if len(patterns) == 0 {
		return line
	}

	// Build a regex to find any of the sensitive keys followed by '=' and a value.
	// The value is considered any sequence of non-whitespace characters.
	// Example: (key1|key2)=<value>
	re := regexp.MustCompile(`(` + strings.Join(patterns, "|") + `)=([\s]*)`)

	// Replace all found occurrences with "key=[ redacted ]"
	return re.ReplaceAllString(line, "$1=[ redacted ]")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant