Skip to content

test(buffer): add functional test for disk buffer corruption recovery (LOG-9386) - #3393

Merged
openshift-merge-bot[bot] merged 1 commit into
openshift:masterfrom
vparfonov:log9386-test
Aug 11, 2026
Merged

test(buffer): add functional test for disk buffer corruption recovery (LOG-9386)#3393
openshift-merge-bot[bot] merged 1 commit into
openshift:masterfrom
vparfonov:log9386-test

Conversation

@vparfonov

@vparfonov vparfonov commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Description

Verify that Vector does not CrashLoop when the disk buffer contains corrupted protobuf records. The test corrupts buffer record payloads while the collector is running, then kills it so the restart reads the corrupted buffer. Asserts that Vector logs a warning about corrupted records during seek, starts successfully, and continues delivering logs after recovery.

/cc @Clee2691
/assign @jcantrill

Links

Summary by CodeRabbit

  • Tests
    • Added functional coverage for recovery when disk-buffer records are corrupted.
    • Verified corrupted records are detected and handled without repeated restart loops.
    • Confirmed the collector restarts once, resumes delivery, and preserves recoverable records.
    • Improved functional test support for inspecting and troubleshooting collector behavior during recovery scenarios.

@openshift-ci
openshift-ci Bot requested review from Clee2691 and cahartma August 10, 2026 07:53
@qodo-for-rh-openshift

qodo-for-rh-openshift Bot commented Aug 10, 2026

Copy link
Copy Markdown

PR Summary by Qodo

Add functional test for Vector disk buffer corruption recovery

🧪 Tests ✨ Enhancement 🕐 40+ Minutes

Grey Divider

AI Description

• Add a tools sidecar option to share volumes with the collector during functional tests.
• Introduce a helper to corrupt Vector disk-buffer records while preserving CRC validity.
• Add a functional test asserting Vector restarts, warns, and continues delivery after corruption.
Diagram

graph TD
  A["Ginkgo functional test"] --> B["Functional framework"] --> C["Collector Pod"] --> D[("Disk buffer .dat")]
  E["HTTP sink container"] --> C --> E
  F["Tools sidecar"] --> D --> G["Corrupted records"]
  B --> F --> B
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Corrupt in-place inside the tools container (no base64 round-trip)
  • ➕ Avoids base64 encoding/ARG_MAX chunking complexity
  • ➕ Avoids copying large files through exec output
  • ➖ Would require shipping a purpose-built binary/script into the image (or using a larger image with tooling)
  • ➖ Harder to keep deterministic, portable corruption logic across environments
2. Use Kubernetes copy APIs (e.g., oc/kubectl cp) to pull/push the .dat file
  • ➕ Simplifies transfer logic vs manual base64 chunking
  • ➕ More readable test code
  • ➖ Introduces reliance on external CLI behaviors and tar streaming semantics
  • ➖ Often less stable in CI and harder to debug when copy fails
3. Use ephemeral debug container instead of a permanent sidecar
  • ➕ No persistent extra container for tests that don’t need tools
  • ➕ Closer to real operational debugging flow
  • ➖ Ephemeral containers are not always enabled/available in all test clusters
  • ➖ More orchestration complexity in the test framework

Recommendation: The PR’s approach (dedicated tools sidecar + shared EmptyDir volume) is a pragmatic, CI-friendly pattern: it keeps the collector image unchanged, provides deterministic access to the buffer directory, and avoids cluster feature dependencies. The base64 chunking is slightly verbose, but it is reliable under exec/ARG_MAX constraints and keeps the corruption logic test-local and reproducible.

Files changed (3) +383 / -0

Enhancement (1) +16 / -0
framework.goAdd tools sidecar visitor with shared EmptyDir volume +16/-0

Add tools sidecar visitor with shared EmptyDir volume

• Introduces a ToolsContainerName constant and a helper visitor that mounts a shared EmptyDir volume into both the collector and a new 'tools' container. The tools container runs an infinite sleep to allow exec-based utilities during tests.

test/framework/functional/framework.go

Tests (2) +367 / -0
corrupt_buffer.goAdd helper to corrupt Vector disk buffer payloads while preserving CRC +90/-0

Add helper to corrupt Vector disk buffer payloads while preserving CRC

• Adds utilities that parse buffer records from a .dat file, flip payload bytes, and recompute CRC32-IEEE so checksum validation passes but protobuf decoding fails. Leaves the last record intact to avoid writer-side validation issues.

test/functional/misc/corrupt_buffer.go

disk_buffer_corruption_test.goAdd functional test asserting recovery from corrupted disk-buffer records +277/-0

Add functional test asserting recovery from corrupted disk-buffer records

• Creates a Ginkgo functional test that forces buffering by SIGSTOP-ing the HTTP sink, writes a burst of logs, corrupts the disk buffer via a tools sidecar, then kills Vector to trigger restart. Verifies Vector starts, logs a corruption warning during initialization seek, avoids CrashLoopBackOff, and resumes delivering logs after recovery.

test/functional/misc/disk_buffer_corruption_test.go

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 42a7c914-4974-4ac7-9bc5-00d57113ec1d

📥 Commits

Reviewing files that changed from the base of the PR and between a59a8f4 and 25a51a7.

📒 Files selected for processing (1)
  • test/functional/misc/disk_buffer_corruption_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/functional/misc/disk_buffer_corruption_test.go

📝 Walkthrough

Walkthrough

Adds a tools sidecar visitor for shared disk access, helpers that corrupt Vector disk-buffer records while preserving checksums, and a functional test that verifies collector recovery and resumed delivery.

Changes

Disk-buffer recovery validation

Layer / File(s) Summary
Tools container access
test/framework/functional/framework.go
Adds the tools container visitor with a shared emptyDir volume.
Disk-buffer record corruption
test/functional/misc/corrupt_buffer.go, test/functional/misc/disk_buffer_corruption_test.go
Parses length-prefixed records, corrupts payloads, recalculates CRC32 checksums, validates bounds, and rewrites the buffer file.
Collector recovery scenario
test/functional/misc/disk_buffer_corruption_test.go
Buffers messages while the receiver is frozen, corrupts a disk-buffer file, restarts the collector, checks recovery logs and restart behavior, then verifies post-restart delivery.

Estimated code review effort: 4 (Complex) | ~45 minutes

Suggested reviewers: clee2691, cahartma

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding a functional test for disk buffer corruption recovery.
Description check ✅ Passed The description explains the test intent and implementation, assigns a reviewer and approver, and links the dependent PR and JIRA issue.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@vparfonov
vparfonov marked this pull request as draft August 10, 2026 07:54
@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Aug 10, 2026
@qodo-for-rh-openshift

qodo-for-rh-openshift Bot commented Aug 10, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Buffer file rewrite race ✓ Resolved 🐞 Bug ☼ Reliability ⭐ New
Description
corruptBufferFile overwrites the disk-buffer .dat file while the collector is explicitly still
running and buffering, then asserts an exact byte-size match. Concurrent writes/appends can change
the file during the read/overwrite/size-check window, making the test flaky and potentially not
exercising the intended corruption-on-restart scenario.
Code

test/functional/misc/disk_buffer_corruption_test.go[R271-274]

+	sizeStr, err := framework.RunCommand(functional.ToolsContainerName, "bash", "-c", sizeCmd)
+	Expect(err).To(BeNil())
+	Expect(strings.TrimSpace(sizeStr)).To(Equal(fmt.Sprintf("%d", len(corruptedData))),
+		"Corrupted buffer file size on disk does not match expected size")
Relevance

●●● Strong

Strong precedent fixing functional-test flakes by removing races via polling/Eventually patterns.

PR-#3256
PR-#3337

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The test freezes only the HTTP receiver, then corrupts the buffer "while collector is still
running"; the corruption helper rewrites the .dat file and immediately asserts the on-disk byte
size equals the locally corrupted snapshot, which can be invalidated by concurrent collector writes.

test/functional/misc/disk_buffer_corruption_test.go[72-96]
test/functional/misc/disk_buffer_corruption_test.go[223-275]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The test rewrites the disk buffer data file while the collector can still be writing to it (output is frozen, collector continues buffering). This can cause intermittent failures (size mismatch) and/or reduce determinism of the corruption scenario.

### Issue Context
The test intentionally corrupts the buffer while the collector is running, but it then performs an exact file-size assertion immediately after rewriting the file. If the collector appends to the same file (or switches files) during the operation, the rewritten file’s size/content can drift.

### Fix Focus Areas
- test/functional/misc/disk_buffer_corruption_test.go[72-96]
- test/functional/misc/disk_buffer_corruption_test.go[161-185]
- test/functional/misc/disk_buffer_corruption_test.go[223-275]

### Suggested fix direction
- Ensure the buffer file is quiescent before rewriting it (e.g., SIGSTOP the collector/vector process briefly, or poll until the selected `.dat` file size is stable across multiple intervals).
- Consider removing or relaxing the exact size equality assertion, or validating corruption via a content marker (e.g., successful rewrite + later startup warning), since exact size is not stable under concurrent writes.
- If you keep rewriting while the collector runs, use a safer write strategy (e.g., write to a temp file and `mv` atomically) and then re-check stability.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Brittle buffer flush timing ✓ Resolved 🐞 Bug ☼ Reliability
Description
The new test assumes the disk buffer file exists after a fixed 5s sleep and then does a single `find
... | head -1`, failing immediately if buffering/flush hasn’t occurred yet. This makes the test
timing-dependent and prone to intermittent failures under cluster load.
Code

test/functional/misc/disk_buffer_corruption_test.go[R83-88]

+		By("waiting for Vector to buffer the messages")
+		time.Sleep(5 * time.Second)
+
+		By("corrupting the disk buffer via the tools sidecar while collector is still running")
+		findCmd := fmt.Sprintf(`find %s -name 'buffer-data-*.dat' 2>/dev/null | head -1`, dataPath)
+		datFilePath, err := framework.RunCommand(functional.ToolsContainerName, "bash", "-c", findCmd)
Relevance

●● Moderate

Polling would reduce flakes, but timing strategies in tests are subjective; no clear precedent.

PR-#3275

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The test explicitly sleeps and then immediately expects a found buffer file path to be non-empty; if
the file hasn’t been created/flushed yet, it fails. The framework already has polling helpers for
similar eventual-consistency reads.

test/functional/misc/disk_buffer_corruption_test.go[83-92]
test/framework/functional/read.go[171-180]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The test uses a fixed sleep and a one-shot file lookup for `buffer-data-*.dat`; if the file isn’t present yet, the test fails even though the system may still be working correctly.

### Issue Context
Disk buffer flushing is asynchronous, and the test already uses polling patterns elsewhere for readiness.

### Fix Focus Areas
- Replace `time.Sleep(5s)` + single-shot `find | head -1` with `wait.PollUntilContextTimeout` to wait for:
 - at least one matching file to exist
 - (optionally) file size > 0 and stable across two polls
 - choose the newest file (e.g., `ls -t ... | head -1`) rather than an arbitrary first match

### Fix Focus Areas (code)
- test/functional/misc/disk_buffer_corruption_test.go[83-92]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Tools sidecar bash dependency 🐞 Bug ☼ Reliability ⭐ New
Description
The new tools sidecar is used exclusively via RunCommand(..., "bash", "-c", ...), but the sidecar
definition doesn’t enforce/provision bash (it just runs sleep infinity). If bash is
unavailable in the tools image at runtime, these commands fail and the functional test aborts before
validating corruption recovery.
Code

test/functional/misc/disk_buffer_corruption_test.go[R167-170]

+		out, err := framework.RunCommand(functional.ToolsContainerName, "bash", "-c", findCmd)
+		if err != nil || strings.TrimSpace(out) == "" {
+			return false, nil
+		}
Relevance

●●● Strong

Team often hardens functional tests; will likely ensure tools container has required shell/commands.

PR-#3345
PR-#3337

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
AddToolsContainerVisitor adds a generic tools sidecar that just sleeps, while the test executes
multiple bash -c commands in that container (find/size checks and base64 read/write). This creates
an implicit runtime dependency on bash being available in the tools image.

test/framework/functional/framework.go[195-206]
test/functional/misc/disk_buffer_corruption_test.go[164-173]
test/functional/misc/disk_buffer_corruption_test.go[227-229]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The test assumes `bash` exists in the tools sidecar and uses it for all tooling commands. The tools container definition does not guarantee that assumption, so the test can fail early if the image environment lacks `bash`.

### Issue Context
The tools sidecar is started with a simple sleep command and no bootstrap/install step. The test then execs into it using `bash -c` for `ls`, `wc`, `base64`, and chunked writes.

### Fix Focus Areas
- test/framework/functional/framework.go[195-206]
- test/functional/misc/disk_buffer_corruption_test.go[164-173]
- test/functional/misc/disk_buffer_corruption_test.go[223-274]

### Suggested fix direction
- Prefer `sh -c` with POSIX-safe commands to minimize shell dependency.
- Or change the tools image / init to guarantee `bash` (and required utilities) are present.
- Optionally add a quick preflight check in the test (e.g., `command -v bash`) to fail fast with a clear error message.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. RestartCount not parsed ✓ Resolved 🐞 Bug ≡ Correctness
Description
The restart wait condition compares the JSONPath restartCount output as a raw string, without
parsing/validating it as an integer. If the output is malformed/unexpected, the poll can behave
incorrectly (including reporting a restart when parsing actually failed).
Code

test/functional/misc/disk_buffer_corruption_test.go[R152-155]

+			if err != nil {
+				return false, nil
+			}
+			return strings.TrimSpace(countStr) >= "1", nil
Relevance

●●● Strong

String-compare restartCount is correctness bug; parsing int is straightforward and safer.

PR-#3275

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The poll condition directly compares strings.TrimSpace(countStr) to the literal string "1" instead
of parsing it as an integer, so it doesn’t validate that the output is a numeric restart count.

test/functional/misc/disk_buffer_corruption_test.go[146-156]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`restartCount` is treated as a string and compared without numeric parsing/validation.

### Issue Context
`oc ... OutputJsonpath(...)` returns text; it should be trimmed and parsed via `strconv.Atoi` to ensure correctness and make malformed output a retry condition.

### Fix Focus Areas
- Replace string comparison with:
 - `n, err := strconv.Atoi(strings.TrimSpace(countStr))`
 - on parse error: return `(false, nil)` so the poll continues (or return the error if you want to fail fast)
 - return `n >= 1`
- Similarly, later `Expect(...).To(Equal("1"))` can parse and assert `n == 1` for robustness.

### Fix Focus Areas (code)
- test/functional/misc/disk_buffer_corruption_test.go[146-156]
- test/functional/misc/disk_buffer_corruption_test.go[176-183]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Unpinned tools image tag 🐞 Bug ⚙ Maintainability
Description
AddToolsContainerVisitor hard-codes the tools sidecar image as ubi-minimal:latest, making functional
tests non-reproducible and susceptible to upstream image changes. This can cause CI to start failing
without any source change in this repo.
Code

test/framework/functional/framework.go[R203-206]

+		b.AddContainer(ToolsContainerName, "registry.access.redhat.com/ubi9/ubi-minimal:latest").
+			AddVolumeMount(volumeName, mountPath, "", false).
+			WithCmd([]string{"sleep", "infinity"}).
+			End()
Relevance

●● Moderate

Repo already uses mutable :latest in tooling; pinning may be desired but not clearly enforced.

PR-#3280

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The framework adds a new tools sidecar using a mutable :latest tag, which can change contents
across time and break reproducibility.

test/framework/functional/framework.go[195-206]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The tools sidecar image is referenced with the mutable `:latest` tag, so the test environment can change over time.

### Issue Context
This is introduced in the functional framework helper used to add a "tools" container.

### Fix Focus Areas
- Pin the image to a specific version or (preferably) an immutable digest.
- Consider using an image already managed/pinned by the test framework (if available) to avoid introducing a new external moving dependency.

### Fix Focus Areas (code)
- test/framework/functional/framework.go[195-206]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View review recommended (1)
6. Ignored exec command errors ✓ Resolved 🐞 Bug ☼ Reliability
Description
The test discards errors from critical setup/trigger steps (STOP/CONT the HTTP receiver and killing
PID 1 in the collector), so failures in those commands can invalidate the scenario and lead to
misleading later assertions. This reduces debuggability and can turn environment issues into
confusing test failures.
Code

test/functional/misc/disk_buffer_corruption_test.go[R72-74]

+		By("freezing the HTTP receiver and writing a burst of messages to fill the buffer")
+		_, _ = framework.RunCommand(string(obs.OutputTypeHTTP), "bash", "-c", "kill -STOP 1")
+
Relevance

●● Moderate

Improves debuggability, but team has recently rejected some test-quality nits; uncertain they’ll
change it.

PR-#3275

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The test uses _ , _ = framework.RunCommand(...) for receiver STOP/CONT and for killing PID 1,
which discards errors and hides whether the intended state transitions occurred.

test/functional/misc/disk_buffer_corruption_test.go[72-74]
test/functional/misc/disk_buffer_corruption_test.go[142-143]
test/functional/misc/disk_buffer_corruption_test.go[184-187]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Errors from key `RunCommand` calls are ignored, so the test can proceed without actually freezing the receiver or killing the collector.

### Issue Context
These commands are essential to making Vector buffer to disk and to triggering the restart that exercises corruption recovery.

### Fix Focus Areas
- Capture and assert `err` for:
 - `kill -STOP 1`
 - `kill 1`
 - `kill -CONT 1`
 - truncation of the receiver output file
- When an error occurs, include the command output in the assertion message to aid debugging.

### Fix Focus Areas (code)
- test/functional/misc/disk_buffer_corruption_test.go[72-74]
- test/functional/misc/disk_buffer_corruption_test.go[142-143]
- test/functional/misc/disk_buffer_corruption_test.go[184-187]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

7. Temp file handle leaked ✓ Resolved 🐞 Bug ☼ Reliability
Description
The test creates a temp file with os.CreateTemp but never closes the returned file handle. This
leaks a file descriptor for the lifetime of the test process.
Code

test/functional/misc/disk_buffer_corruption_test.go[R101-104]

+		tmpFile, err := os.CreateTemp("", "buffer-data-*.dat")
+		Expect(err).To(BeNil())
+		defer func() { _ = os.Remove(tmpFile.Name()) }()
+		Expect(os.WriteFile(tmpFile.Name(), rawData, 0o640)).To(Succeed())
Relevance

●●● Strong

Deterministic resource leak fix: close temp file handle; low-risk and standard Go practice.

PR-#3275

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The code stores the result of os.CreateTemp but doesn’t call Close() on it before proceeding to
write/read by path.

test/functional/misc/disk_buffer_corruption_test.go[101-105]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`os.CreateTemp` returns an open file descriptor that isn’t closed.

### Issue Context
The test only needs a temporary path; it subsequently writes via `os.WriteFile` using the name.

### Fix Focus Areas
- Add `defer tmpFile.Close()` after creation (handle the error if desired).
- Alternatively, create a temp dir or use `os.CreateTemp` only to get a unique name, close immediately, and then use `os.WriteFile`.

### Fix Focus Areas (code)
- test/functional/misc/disk_buffer_corruption_test.go[101-105]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context used
⚠️ Tickets: not configured — ticket URL found in PR but could not be fetched — check ticket provider credentials
✅ Compliance rules (platform): 9 rules

Grey Divider

Tip of the day
💡 Did you know, you can group findings by type and pick your Finding display, from Minimal to Full

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Previous review results

Review updated until commit 25a51a7

Results up to commit e995fa1 ⚖️ Balanced


🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Action required
1. Brittle buffer flush timing ✓ Resolved 🐞 Bug ☼ Reliability
Description
The new test assumes the disk buffer file exists after a fixed 5s sleep and then does a single `find
... | head -1`, failing immediately if buffering/flush hasn’t occurred yet. This makes the test
timing-dependent and prone to intermittent failures under cluster load.
Code

test/functional/misc/disk_buffer_corruption_test.go[R83-88]

+		By("waiting for Vector to buffer the messages")
+		time.Sleep(5 * time.Second)
+
+		By("corrupting the disk buffer via the tools sidecar while collector is still running")
+		findCmd := fmt.Sprintf(`find %s -name 'buffer-data-*.dat' 2>/dev/null | head -1`, dataPath)
+		datFilePath, err := framework.RunCommand(functional.ToolsContainerName, "bash", "-c", findCmd)
Relevance

●● Moderate

Polling would reduce flakes, but timing strategies in tests are subjective; no clear precedent.

PR-#3275

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The test explicitly sleeps and then immediately expects a found buffer file path to be non-empty; if
the file hasn’t been created/flushed yet, it fails. The framework already has polling helpers for
similar eventual-consistency reads.

test/functional/misc/disk_buffer_corruption_test.go[83-92]
test/framework/functional/read.go[171-180]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The test uses a fixed sleep and a one-shot file lookup for `buffer-data-*.dat`; if the file isn’t present yet, the test fails even though the system may still be working correctly.

### Issue Context
Disk buffer flushing is asynchronous, and the test already uses polling patterns elsewhere for readiness.

### Fix Focus Areas
- Replace `time.Sleep(5s)` + single-shot `find | head -1` with `wait.PollUntilContextTimeout` to wait for:
 - at least one matching file to exist
 - (optionally) file size > 0 and stable across two polls
 - choose the newest file (e.g., `ls -t ... | head -1`) rather than an arbitrary first match

### Fix Focus Areas (code)
- test/functional/misc/disk_buffer_corruption_test.go[83-92]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended
2. RestartCount not parsed ✓ Resolved 🐞 Bug ≡ Correctness
Description
The restart wait condition compares the JSONPath restartCount output as a raw string, without
parsing/validating it as an integer. If the output is malformed/unexpected, the poll can behave
incorrectly (including reporting a restart when parsing actually failed).
Code

test/functional/misc/disk_buffer_corruption_test.go[R152-155]

+			if err != nil {
+				return false, nil
+			}
+			return strings.TrimSpace(countStr) >= "1", nil
Relevance

●●● Strong

String-compare restartCount is correctness bug; parsing int is straightforward and safer.

PR-#3275

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The poll condition directly compares strings.TrimSpace(countStr) to the literal string "1" instead
of parsing it as an integer, so it doesn’t validate that the output is a numeric restart count.

test/functional/misc/disk_buffer_corruption_test.go[146-156]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`restartCount` is treated as a string and compared without numeric parsing/validation.

### Issue Context
`oc ... OutputJsonpath(...)` returns text; it should be trimmed and parsed via `strconv.Atoi` to ensure correctness and make malformed output a retry condition.

### Fix Focus Areas
- Replace string comparison with:
 - `n, err := strconv.Atoi(strings.TrimSpace(countStr))`
 - on parse error: return `(false, nil)` so the poll continues (or return the error if you want to fail fast)
 - return `n >= 1`
- Similarly, later `Expect(...).To(Equal("1"))` can parse and assert `n == 1` for robustness.

### Fix Focus Areas (code)
- test/functional/misc/disk_buffer_corruption_test.go[146-156]
- test/functional/misc/disk_buffer_corruption_test.go[176-183]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Unpinned tools image tag 🐞 Bug ⚙ Maintainability
Description
AddToolsContainerVisitor hard-codes the tools sidecar image as ubi-minimal:latest, making functional
tests non-reproducible and susceptible to upstream image changes. This can cause CI to start failing
without any source change in this repo.
Code

test/framework/functional/framework.go[R203-206]

+		b.AddContainer(ToolsContainerName, "registry.access.redhat.com/ubi9/ubi-minimal:latest").
+			AddVolumeMount(volumeName, mountPath, "", false).
+			WithCmd([]string{"sleep", "infinity"}).
+			End()
Relevance

●● Moderate

Repo already uses mutable :latest in tooling; pinning may be desired but not clearly enforced.

PR-#3280

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The framework adds a new tools sidecar using a mutable :latest tag, which can change contents
across time and break reproducibility.

test/framework/functional/framework.go[195-206]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The tools sidecar image is referenced with the mutable `:latest` tag, so the test environment can change over time.

### Issue Context
This is introduced in the functional framework helper used to add a "tools" container.

### Fix Focus Areas
- Pin the image to a specific version or (preferably) an immutable digest.
- Consider using an image already managed/pinned by the test framework (if available) to avoid introducing a new external moving dependency.

### Fix Focus Areas (code)
- test/framework/functional/framework.go[195-206]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Ignored exec command errors ✓ Resolved 🐞 Bug ☼ Reliability
Description
The test discards errors from critical setup/trigger steps (STOP/CONT the HTTP receiver and killing
PID 1 in the collector), so failures in those commands can invalidate the scenario and lead to
misleading later assertions. This reduces debuggability and can turn environment issues into
confusing test failures.
Code

test/functional/misc/disk_buffer_corruption_test.go[R72-74]

+		By("freezing the HTTP receiver and writing a burst of messages to fill the buffer")
+		_, _ = framework.RunCommand(string(obs.OutputTypeHTTP), "bash", "-c", "kill -STOP 1")
+
Relevance

●● Moderate

Improves debuggability, but team has recently rejected some test-quality nits; uncertain they’ll
change it.

PR-#3275

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The test uses _ , _ = framework.RunCommand(...) for receiver STOP/CONT and for killing PID 1,
which discards errors and hides whether the intended state transitions occurred.

test/functional/misc/disk_buffer_corruption_test.go[72-74]
test/functional/misc/disk_buffer_corruption_test.go[142-143]
test/functional/misc/disk_buffer_corruption_test.go[184-187]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Errors from key `RunCommand` calls are ignored, so the test can proceed without actually freezing the receiver or killing the collector.

### Issue Context
These commands are essential to making Vector buffer to disk and to triggering the restart that exercises corruption recovery.

### Fix Focus Areas
- Capture and assert `err` for:
 - `kill -STOP 1`
 - `kill 1`
 - `kill -CONT 1`
 - truncation of the receiver output file
- When an error occurs, include the command output in the assertion message to aid debugging.

### Fix Focus Areas (code)
- test/functional/misc/disk_buffer_corruption_test.go[72-74]
- test/functional/misc/disk_buffer_corruption_test.go[142-143]
- test/functional/misc/disk_buffer_corruption_test.go[184-187]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational
5. Temp file handle leaked ✓ Resolved 🐞 Bug ☼ Reliability
Description
The test creates a temp file with os.CreateTemp but never closes the returned file handle. This
leaks a file descriptor for the lifetime of the test process.
Code

test/functional/misc/disk_buffer_corruption_test.go[R101-104]

+		tmpFile, err := os.CreateTemp("", "buffer-data-*.dat")
+		Expect(err).To(BeNil())
+		defer func() { _ = os.Remove(tmpFile.Name()) }()
+		Expect(os.WriteFile(tmpFile.Name(), rawData, 0o640)).To(Succeed())
Relevance

●●● Strong

Deterministic resource leak fix: close temp file handle; low-risk and standard Go practice.

PR-#3275

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The code stores the result of os.CreateTemp but doesn’t call Close() on it before proceeding to
write/read by path.

test/functional/misc/disk_buffer_corruption_test.go[101-105]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`os.CreateTemp` returns an open file descriptor that isn’t closed.

### Issue Context
The test only needs a temporary path; it subsequently writes via `os.WriteFile` using the name.

### Fix Focus Areas
- Add `defer tmpFile.Close()` after creation (handle the error if desired).
- Alternatively, create a temp dir or use `os.CreateTemp` only to get a unique name, close immediately, and then use `os.WriteFile`.

### Fix Focus Areas (code)
- test/functional/misc/disk_buffer_corruption_test.go[101-105]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Qodo Logo

Comment on lines +203 to +206
b.AddContainer(ToolsContainerName, "registry.access.redhat.com/ubi9/ubi-minimal:latest").
AddVolumeMount(volumeName, mountPath, "", false).
WithCmd([]string{"sleep", "infinity"}).
End()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

1. Unpinned tools image tag 🐞 Bug ⚙ Maintainability

AddToolsContainerVisitor hard-codes the tools sidecar image as ubi-minimal:latest, making functional
tests non-reproducible and susceptible to upstream image changes. This can cause CI to start failing
without any source change in this repo.
Agent Prompt
### Issue description
The tools sidecar image is referenced with the mutable `:latest` tag, so the test environment can change over time.

### Issue Context
This is introduced in the functional framework helper used to add a "tools" container.

### Fix Focus Areas
- Pin the image to a specific version or (preferably) an immutable digest.
- Consider using an image already managed/pinned by the test framework (if available) to avoid introducing a new external moving dependency.

### Fix Focus Areas (code)
- test/framework/functional/framework.go[195-206]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread test/functional/misc/disk_buffer_corruption_test.go Outdated
Comment thread test/functional/misc/disk_buffer_corruption_test.go Outdated
Comment thread test/functional/misc/disk_buffer_corruption_test.go Outdated
Comment thread test/functional/misc/disk_buffer_corruption_test.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (8)
test/functional/misc/disk_buffer_corruption_test.go (4)

146-157: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Parse restartCount as an integer.

Line 155 compares restartCount as a string: strings.TrimSpace(countStr) >= "1". This is a lexicographic comparison, not a numeric one. It happens to work for the observed values, but it breaks for any zero-padded or unexpected output and it hides intent.

♻️ Proposed fix
-		return strings.TrimSpace(countStr) >= "1", nil
+		count, convErr := strconv.Atoi(strings.TrimSpace(countStr))
+		if convErr != nil {
+			return false, nil
+		}
+		return count >= 1, nil

Add the import:

import "strconv"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/functional/misc/disk_buffer_corruption_test.go` around lines 146 - 157,
Update the restart-count check in the PollUntilContextTimeout callback to trim
countStr, parse it with strconv.Atoi, and compare the resulting integer against
1. Preserve the existing retry behavior when the command or parsing fails, and
add the strconv import.

159-172: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The assertions depend on exact Vector log strings.

Lines 166, 169, and 171 match "Vector has started.", "Corrupted record found during buffer initialization seek", and "Healthcheck failed.". These strings come from Vector internals and change between releases. The middle string is the point of the test, so keep it. The "Healthcheck failed." assertion at line 171 adds little: it only restates that the receiver is still frozen, and it couples the test to an unrelated log message.

Consider removing the healthcheck assertion, or replacing it with a check on delivery behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/functional/misc/disk_buffer_corruption_test.go` around lines 159 - 172,
Remove the exact “Healthcheck failed.” log assertion from the restart
verification in the disk corruption test. Keep the corruption-warning assertion
and startup wait unchanged; do not add a replacement unless an existing
delivery-behavior check is readily available in this test.

184-196: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Wait for the post-restart message.

ReadFileFrom polls cat every 10 seconds, but it returns after the first successful non-empty result. Replayed disk-buffer records can satisfy that condition before the five new records arrive. Poll a bounded read and ContainSubstring(postRestartMessage) with Eventually; avoid nesting a two-minute timeout around the helper’s five-minute maximum read duration.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/functional/misc/disk_buffer_corruption_test.go` around lines 184 - 196,
Replace the immediate post-restart ReadFileFrom assertion with a bounded
Eventually that repeatedly reads the HTTP application log and checks for
postRestartMessage via ContainSubstring. Use a polling duration and timeout that
do not wrap ReadFileFrom’s five-minute maximum duration, while preserving error
validation for each read.

119-133: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Use one upload operation for the corrupted buffer.

framework.RunCommand invokes oc exec for each 64 KiB chunk. A 1 MiB buffer requires 16 exec calls, and a 4 MiB buffer requires 64. Add a framework-level streaming or copy path because oc.Exec does not expose stdin support.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/functional/misc/disk_buffer_corruption_test.go` around lines 119 - 133,
Replace the per-chunk framework.RunCommand loop in the corrupted-buffer setup
with a framework-level streaming or copy operation that uploads the complete
corrupted buffer in one command. Extend the relevant framework/container
execution API, since oc.Exec lacks stdin support, and preserve the subsequent
base64 decode and staging-file cleanup flow.
test/functional/misc/corrupt_buffer.go (2)

10-19: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Move the type doc comment to the type.

The comment block at lines 10-18 describes corruptDiskBufferPayload, but it is attached to corruptDiskBufferResult because line 19 continues the same block. Godoc renders the whole block as the type documentation.

♻️ Proposed fix
-// corruptDiskBufferPayload corrupts the protobuf payload of records in a
-// Vector disk buffer data file while keeping the rkyv record structure and CRC32
-// checksum valid. This causes Vector's T::decode() to fail with
-// ReaderError::Decode — the specific error path fixed by
-// vectordotdev/vector#25691 (LOG-9386).
-//
-// The last record is left intact because Vector's writer validates it during
-// initialization (writer.validate_last_write). Only the reader's seek path
-// uses is_bad_read() to skip decode errors.
 // corruptDiskBufferResult holds the outcome of a corruption operation.
 type corruptDiskBufferResult struct {
 	TotalRecords     int
 	CorruptedRecords int
 	FileBytes        int
 }
 
+// corruptDiskBufferPayload corrupts the protobuf payload of records in a
+// Vector disk buffer data file while keeping the rkyv record structure and CRC32
+// checksum valid. This causes Vector's T::decode() to fail with
+// ReaderError::Decode — the specific error path fixed by
+// vectordotdev/vector#25691 (LOG-9386).
+//
+// The last record is left intact because Vector's writer validates it during
+// initialization (writer.validate_last_write). Only the reader's seek path
+// uses is_bad_read() to skip decode errors.
 func corruptDiskBufferPayload(datFilePath string) (*corruptDiskBufferResult, error) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/functional/misc/corrupt_buffer.go` around lines 10 - 19, Move the
descriptive doc comment for corruptDiskBufferPayload so it directly precedes
that function, and separate it from the corruptDiskBufferResult documentation.
Add or retain a distinct doc comment for corruptDiskBufferResult that describes
the result type.

77-112: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Document the pinned Vector archive version

Vector v0.54.0 uses rkyv 0.7.46 and crc32fast::Hasher, so crc32.NewIEEE() matches its BE(id) || BE(metadata) || payload checksum calculation.

Add these versions to the layout comment. Add a focused test for the synthetic record and checksum to detect future layout drift.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/functional/misc/corrupt_buffer.go` around lines 77 - 112, Update the
ArchivedRecord layout comment near the checksum logic to document the pinned
Vector v0.54.0, rkyv 0.7.46, and crc32fast::Hasher versions and checksum
assumptions. Add a focused test covering the synthetic record and expected
checksum, using the existing corruption/checksum helpers, so future layout or
checksum drift is detected.
test/framework/functional/framework.go (2)

197-202: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Guard GetContainer when the collector is absent.

GetContainer returns a builder with a nil container when no match exists, so AddVolumeMount panics. DeployWithVisitors currently adds constants.CollectorName first. Guard this precondition if callers can provide an arbitrary PodBuilder. WithCmd requires at least one argument; the current call is valid.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/framework/functional/framework.go` around lines 197 - 202, Update
AddToolsContainerVisitor to verify that GetContainer(constants.CollectorName)
returns a valid container before calling AddVolumeMount, returning an
appropriate error when the collector is absent while preserving the existing
volume setup for valid builders.

203-206: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Make the tools image configurable and pin the default image.

Read TOOLS_IMAGE with os.Getenv and use a pinned default. Do not use utils.GetEnvVar; it accepts []v1.EnvVar, not a default string. Use an image that contains bash, find, base64, and wc, or install the required packages. Avoid :latest because it can change between runs and fail on clusters without access to the registry.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/framework/functional/framework.go` around lines 203 - 206, Update the
tools-container setup around ToolsContainerName to read TOOLS_IMAGE via
os.Getenv, falling back to a pinned image tag that provides bash, find, base64,
and wc (or installs them). Replace the hardcoded :latest image while preserving
the existing volume mount, command, and container configuration.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/functional/misc/disk_buffer_corruption_test.go`:
- Around line 101-104: Close the file returned by os.CreateTemp in the
temporary-file setup around tmpFile before writing with os.WriteFile, while
preserving the existing cleanup via os.Remove and subsequent test behavior.

---

Nitpick comments:
In `@test/framework/functional/framework.go`:
- Around line 197-202: Update AddToolsContainerVisitor to verify that
GetContainer(constants.CollectorName) returns a valid container before calling
AddVolumeMount, returning an appropriate error when the collector is absent
while preserving the existing volume setup for valid builders.
- Around line 203-206: Update the tools-container setup around
ToolsContainerName to read TOOLS_IMAGE via os.Getenv, falling back to a pinned
image tag that provides bash, find, base64, and wc (or installs them). Replace
the hardcoded :latest image while preserving the existing volume mount, command,
and container configuration.

In `@test/functional/misc/corrupt_buffer.go`:
- Around line 10-19: Move the descriptive doc comment for
corruptDiskBufferPayload so it directly precedes that function, and separate it
from the corruptDiskBufferResult documentation. Add or retain a distinct doc
comment for corruptDiskBufferResult that describes the result type.
- Around line 77-112: Update the ArchivedRecord layout comment near the checksum
logic to document the pinned Vector v0.54.0, rkyv 0.7.46, and crc32fast::Hasher
versions and checksum assumptions. Add a focused test covering the synthetic
record and expected checksum, using the existing corruption/checksum helpers, so
future layout or checksum drift is detected.

In `@test/functional/misc/disk_buffer_corruption_test.go`:
- Around line 146-157: Update the restart-count check in the
PollUntilContextTimeout callback to trim countStr, parse it with strconv.Atoi,
and compare the resulting integer against 1. Preserve the existing retry
behavior when the command or parsing fails, and add the strconv import.
- Around line 159-172: Remove the exact “Healthcheck failed.” log assertion from
the restart verification in the disk corruption test. Keep the
corruption-warning assertion and startup wait unchanged; do not add a
replacement unless an existing delivery-behavior check is readily available in
this test.
- Around line 184-196: Replace the immediate post-restart ReadFileFrom assertion
with a bounded Eventually that repeatedly reads the HTTP application log and
checks for postRestartMessage via ContainSubstring. Use a polling duration and
timeout that do not wrap ReadFileFrom’s five-minute maximum duration, while
preserving error validation for each read.
- Around line 119-133: Replace the per-chunk framework.RunCommand loop in the
corrupted-buffer setup with a framework-level streaming or copy operation that
uploads the complete corrupted buffer in one command. Extend the relevant
framework/container execution API, since oc.Exec lacks stdin support, and
preserve the subsequent base64 decode and staging-file cleanup flow.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 63b0e985-8b50-4795-91b6-0b16b2208fd2

📥 Commits

Reviewing files that changed from the base of the PR and between 1cff204 and e995fa1.

📒 Files selected for processing (3)
  • test/framework/functional/framework.go
  • test/functional/misc/corrupt_buffer.go
  • test/functional/misc/disk_buffer_corruption_test.go

Comment thread test/functional/misc/disk_buffer_corruption_test.go Outdated
@vparfonov
vparfonov force-pushed the log9386-test branch 2 times, most recently from 70753ff to db6efc0 Compare August 10, 2026 10:53
@vparfonov
vparfonov marked this pull request as ready for review August 10, 2026 10:53
@openshift-ci openshift-ci Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Aug 10, 2026
@openshift-ci
openshift-ci Bot requested a review from jcantrill August 10, 2026 10:53
Comment thread test/functional/misc/disk_buffer_corruption_test.go
Comment on lines +167 to +170
out, err := framework.RunCommand(functional.ToolsContainerName, "bash", "-c", findCmd)
if err != nil || strings.TrimSpace(out) == "" {
return false, nil
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

2. Tools sidecar bash dependency 🐞 Bug ☼ Reliability

The new tools sidecar is used exclusively via RunCommand(..., "bash", "-c", ...), but the sidecar
definition doesn’t enforce/provision bash (it just runs sleep infinity). If bash is
unavailable in the tools image at runtime, these commands fail and the functional test aborts before
validating corruption recovery.
Agent Prompt
### Issue description
The test assumes `bash` exists in the tools sidecar and uses it for all tooling commands. The tools container definition does not guarantee that assumption, so the test can fail early if the image environment lacks `bash`.

### Issue Context
The tools sidecar is started with a simple sleep command and no bootstrap/install step. The test then execs into it using `bash -c` for `ls`, `wc`, `base64`, and chunked writes.

### Fix Focus Areas
- test/framework/functional/framework.go[195-206]
- test/functional/misc/disk_buffer_corruption_test.go[164-173]
- test/functional/misc/disk_buffer_corruption_test.go[223-274]

### Suggested fix direction
- Prefer `sh -c` with POSIX-safe commands to minimize shell dependency.
- Or change the tools image / init to guarantee `bash` (and required utilities) are present.
- Optionally add a quick preflight check in the test (e.g., `command -v bash`) to fail fast with a clear error message.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@qodo-for-rh-openshift

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit db6efc0

@vparfonov

Copy link
Copy Markdown
Contributor Author

/hold

@openshift-ci openshift-ci Bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Aug 10, 2026
@vparfonov

Copy link
Copy Markdown
Contributor Author

/hold cancel

@openshift-ci openshift-ci Bot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Aug 10, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
test/functional/misc/disk_buffer_corruption_test.go (3)

125-133: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Do not write to the outer err inside the poll closure.

Line 127 assigns the outer err, and line 126 overwrites it with the poll result. The assertion on line 133 therefore never reports the command error. Use a local variable inside the closure.

♻️ Proposed change
 		var sinkResult string
 		err = wait.PollUntilContextTimeout(context.TODO(), 2*time.Second, 90*time.Second, true, func(ctx context.Context) (bool, error) {
-			sinkResult, err = framework.RunCommand(string(obs.OutputTypeHTTP), "cat", functional.ApplicationLogFile)
-			if err != nil {
+			out, readErr := framework.RunCommand(string(obs.OutputTypeHTTP), "cat", functional.ApplicationLogFile)
+			if readErr != nil {
 				return false, nil
 			}
+			sinkResult = out
 			return strings.Contains(sinkResult, fmt.Sprintf("post-corruption-msg-%d", postRestartCount)), nil
 		})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/functional/misc/disk_buffer_corruption_test.go` around lines 125 - 133,
Update the poll closure in the disk-buffer corruption test to capture the
RunCommand error in a local variable rather than assigning the outer err. Keep
the poll result assigned to the outer err so the final Expect(err) assertion
reports polling failures while command errors remain handled within the closure.

77-81: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Resume the frozen receiver in a deferred cleanup.

If any assertion between lines 81 and 116 fails, the receiver process stays in the STOP state and the kill -CONT on line 115 never runs. Ginkgo aborts the It body on failure. framework.Cleanup() deletes the pod, so this is not a leak across tests, but the frozen process hides receiver-side diagnostics in the failure output. Register a DeferCleanup that resumes the process right after you stop it.

♻️ Proposed change
 		out, err := framework.RunCommand(functional.ToolsContainerName, "sh", "-c", fmt.Sprintf("kill -STOP %s", receiverPid))
 		Expect(err).To(BeNil(), "Failed to freeze HTTP receiver: %s", out)
+		DeferCleanup(func() {
+			_, _ = framework.RunCommand(functional.ToolsContainerName, "sh", "-c", fmt.Sprintf("kill -CONT %s", receiverPid))
+		})
 		time.Sleep(5 * time.Second)

Also applies to: 114-116

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/functional/misc/disk_buffer_corruption_test.go` around lines 77 - 81,
After stopping the receiver in the disk-buffer corruption test, immediately
register a Ginkgo DeferCleanup callback that runs kill -CONT for receiverPid and
verifies the command succeeds, ensuring the process is resumed even when later
assertions abort the It body. Remove or consolidate the existing manual resume
at the later cleanup location so the receiver is resumed exactly once.

100-101: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Assert on the corrupted record count at the call site.

corruptBufferFile returns the number of corrupted records, but line 101 discards it. Either assert on it in the test body or drop the return value, because the internal Expect(corruptedCount).To(BeNumerically(">=", 1)) already covers the lower bound.

♻️ Proposed change
-	corruptBufferFile(framework, datFilePath)
+	corruptedCount := corruptBufferFile(framework, datFilePath)
+	By(fmt.Sprintf("corrupted %d buffer records", corruptedCount))

Also applies to: 274-274

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/functional/misc/disk_buffer_corruption_test.go` around lines 100 - 101,
Capture the return value from corruptBufferFile at both call sites in the test
and assert that the corrupted record count meets the expected lower bound;
alternatively, remove the return value if the internal assertion is intended to
be the sole validation. Update the test body around the “corrupting the disk
buffer via the tools sidecar” step without changing the corruption behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/functional/misc/corrupt_buffer.go`:
- Around line 37-40: Remove the single-record fallback that sets corruptUpTo to
1. In the corrupt-buffer setup, detect when len(records) is less than two and
return a clear error immediately, preserving the invariant that the final record
remains intact and allowing the caller to retry or fail explicitly.

In `@test/functional/misc/disk_buffer_corruption_test.go`:
- Around line 256-269: Update waitForCollectorRestart to parse countStr with
strconv.Atoi before comparing it, returning false when parsing fails and
otherwise requiring the numeric restart count to be at least one. Add the
necessary strconv import and preserve the existing polling and error behavior.

---

Nitpick comments:
In `@test/functional/misc/disk_buffer_corruption_test.go`:
- Around line 125-133: Update the poll closure in the disk-buffer corruption
test to capture the RunCommand error in a local variable rather than assigning
the outer err. Keep the poll result assigned to the outer err so the final
Expect(err) assertion reports polling failures while command errors remain
handled within the closure.
- Around line 77-81: After stopping the receiver in the disk-buffer corruption
test, immediately register a Ginkgo DeferCleanup callback that runs kill -CONT
for receiverPid and verifies the command succeeds, ensuring the process is
resumed even when later assertions abort the It body. Remove or consolidate the
existing manual resume at the later cleanup location so the receiver is resumed
exactly once.
- Around line 100-101: Capture the return value from corruptBufferFile at both
call sites in the test and assert that the corrupted record count meets the
expected lower bound; alternatively, remove the return value if the internal
assertion is intended to be the sole validation. Update the test body around the
“corrupting the disk buffer via the tools sidecar” step without changing the
corruption behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: dc309310-a89e-4696-900f-26a70a1026ae

📥 Commits

Reviewing files that changed from the base of the PR and between db6efc0 and 2926140.

📒 Files selected for processing (2)
  • test/functional/misc/corrupt_buffer.go
  • test/functional/misc/disk_buffer_corruption_test.go

Comment thread test/functional/misc/corrupt_buffer.go Outdated
Comment thread test/functional/misc/disk_buffer_corruption_test.go
@vparfonov

Copy link
Copy Markdown
Contributor Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
⚠️ Action not completed

Already reviewed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@jcantrill jcantrill left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

/approve

@openshift-ci

openshift-ci Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: jcantrill, vparfonov

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

The pull request process is described 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

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Aug 10, 2026
@vparfonov

Copy link
Copy Markdown
Contributor Author

/test functional-target

@qodo-for-rh-openshift

qodo-for-rh-openshift Bot commented Aug 11, 2026

Copy link
Copy Markdown

PR-Agent: could not find a component named functional-target in a supported language in this PR.

… (LOG-9386)

Verify that Vector does not CrashLoop when the disk buffer contains
corrupted protobuf records. The test corrupts buffer record payloads
while the collector is running, then kills it so the restart reads the
corrupted buffer. Asserts that Vector logs a warning about corrupted
records during seek, starts successfully, and continues delivering
logs after recovery.

Signed-off-by: Vitalii Parfonov <vparfono@redhat.com>
@openshift-ci

openshift-ci Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

@vparfonov: all tests passed!

Full PR test history. Your PR dashboard.

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-sigs/prow repository. I understand the commands that are listed here.

@Clee2691

Copy link
Copy Markdown
Contributor

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Aug 11, 2026
@openshift-merge-bot
openshift-merge-bot Bot merged commit 8b3de74 into openshift:master Aug 11, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged. release/6.7

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants