Skip to content
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

chore: durability tests #80

Merged
merged 2 commits into from
Sep 26, 2023
Merged

chore: durability tests #80

merged 2 commits into from
Sep 26, 2023

Conversation

rustatian
Copy link
Member

@rustatian rustatian commented Sep 25, 2023

Reason for This PR

  • Beanstalk durability tests

Description of Changes

  • Beanstalk durability tests

License Acceptance

By submitting this pull request, I confirm that my contribution is made under
the terms of the MIT license.

PR Checklist

[Author TODO: Meet these criteria.]
[Reviewer TODO: Verify that these criteria are met. Request changes if not]

  • All commits in this PR are signed (git commit -s).
  • The reason for this PR is clearly provided (issue no. or explanation).
  • The description of changes is clear and encompassing.
  • Any required documentation changes (code and docs) are included in this PR.
  • Any user-facing changes are mentioned in CHANGELOG.md.
  • All added/changed functionality is tested.

Summary by CodeRabbit

  • New Feature: Added a new GitHub Actions workflow for "beanstalk_durability" to ensure the robustness of the Beanstalk server under network failures.
  • Test: Introduced new helper functions EnableProxy, DisableProxy, and DeleteProxy in the helpers package to manage proxies during testing.
  • Test: Added a new test function TestDurabilityBeanstalk that simulates network failures and tests the durability of the Beanstalk server.
  • Chore: Updated CI/CD pipeline command to reflect changes in test file organization.

Signed-off-by: Valery Piashchynski <[email protected]>
@rustatian rustatian added the enhancement New feature or request label Sep 25, 2023
@rustatian rustatian self-assigned this Sep 25, 2023
@coderabbitai
Copy link

coderabbitai bot commented Sep 25, 2023

Walkthrough

This pull request introduces a new durability test for the Beanstalk server, along with associated helper functions and configurations. It also modifies the CI/CD pipeline to accommodate these changes.

Changes

File Summary
.github/workflows/linux.yml Modifies the command used to run tests in the CI/CD pipeline.
.github/workflows/linux_durability.yml Adds a new GitHub Actions workflow for the "beanstalk_durability" project.
tests/configs/...redial.yaml Introduces a new YAML configuration file for the server and job pipelines.
tests/helpers/helpers.go Adds new functions to enable, disable, and delete a proxy.
tests/jobs_beanstalk_durability_test.go Adds a new test function that tests the durability of a Beanstalk server.

🐇💻

In the land of code where the shadows lie,
A rabbit hops, its gaze held high.
With each keystroke, a new world unfurls,
Of tests and proxies, in loops and curls.
The Beanstalk stands, its strength put to test,
As the rabbit watches, it's time to rest.
For in this land where the coders play,
The rabbit has had a productive day. 🌙✨


Tips

Chat with CodeRabbit Bot (@coderabbitai)

  • Mention @coderabbitai in any review comment for bot assistance.
  • Note: Review comments are made on code diffs or files, not on the PR overview.

Pause Incremental Reviews

  • Insert @coderabbitai: ignore in the PR description to halt the bot's ongoing reviews. Remove the line to resume.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Review Status

Actionable comments generated: 4

Commits Files that changed from the base of the PR and between ea26aad and 753bc9d.
Files ignored due to filter (3)
  • go.work.sum
  • tests/go.mod
  • tests/go.sum
Files selected for processing (5)
  • .github/workflows/linux.yml (1 hunks)
  • .github/workflows/linux_durability.yml (1 hunks)
  • tests/configs/.rr-beanstalk-durability-redial.yaml (1 hunks)
  • tests/helpers/helpers.go (2 hunks)
  • tests/jobs_beanstalk_durability_test.go (1 hunks)
Files skipped from review due to trivial changes (2)
  • .github/workflows/linux.yml
  • tests/configs/.rr-beanstalk-durability-redial.yaml
Additional comments (Suppressed): 5
.github/workflows/linux_durability.yml (4)
  • 1-99: The new GitHub Actions workflow linux_durability.yml seems well-structured and follows best practices for setting up the environment, caching dependencies, running tests, and uploading coverage results. However, there are a few points that need to be verified or refined.

  • 16-22: Ensure that the matrix configuration is correct and matches your testing requirements. The current configuration only tests on Ubuntu with PHP 8.2 and the stable version of Go. If you need to support other versions or operating systems, you should add them to the matrix.

  • 70-71: The test command runs a specific Go file (jobs_beanstalk_durability_test.go). If there are other test files that need to be included in this workflow, you should modify the command accordingly. Also, ensure that the -timeout value is appropriate for your tests.

- go test -timeout 20m -v -race -cover -tags=debug -failfast -coverpkg=$(cat pkgs.txt) -coverprofile=./coverage-ci/beanstalk_dur.out -covermode=atomic jobs_beanstalk_durability_test.go
+ go test -timeout 20m -v -race -cover -tags=debug -failfast -coverpkg=$(cat pkgs.txt) -coverprofile=./coverage-ci/beanstalk_dur.out -covermode=atomic ./...
  • 93-94: This command filters out lines not containing 'roadrunner' from the second line onwards in the coverage summary. Ensure that this filtering is necessary and correctly implemented for your use case.
tests/helpers/helpers.go (1)
  • 1-9: The new hunk introduces additional imports (bytes, net/http) to the helpers package. These are used in the newly added functions for managing a Toxiproxy proxy.

Comment on lines +29 to +122
func TestDurabilityBeanstalk(t *testing.T) {
newClient := toxiproxy.NewClient("127.0.0.1:8474")

_, err := newClient.CreateProxy("redial", "127.0.0.1:11400", "127.0.0.1:11300")
require.NoError(t, err)
defer helpers.DeleteProxy("redial", t)

cont := endure.New(slog.LevelDebug, endure.GracefulShutdownTimeout(time.Second*60))

cfg := &config.Plugin{
Version: "2.9.0",
Path: "configs/.rr-beanstalk-durability-redial.yaml",
Prefix: "rr",
}

err = cont.RegisterAll(
cfg,
&server.Plugin{},
&rpcPlugin.Plugin{},
&logger.Plugin{},
&jobs.Plugin{},
&resetter.Plugin{},
&informer.Plugin{},
&beanstalk.Plugin{},
)
require.NoError(t, err)

err = cont.Init()
if err != nil {
t.Fatal(err)
}

ch, err := cont.Serve()
if err != nil {
t.Fatal(err)
}

sig := make(chan os.Signal, 1)
signal.Notify(sig, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)

wg := &sync.WaitGroup{}
wg.Add(1)

stopCh := make(chan struct{}, 1)

go func() {
defer wg.Done()
for {
select {
case e := <-ch:
assert.Fail(t, "error", e.Error.Error())
err = cont.Stop()
if err != nil {
assert.FailNow(t, "error", err.Error())
}
case <-sig:
err = cont.Stop()
if err != nil {
assert.FailNow(t, "error", err.Error())
}
return
case <-stopCh:
// timeout
err = cont.Stop()
if err != nil {
assert.FailNow(t, "error", err.Error())
}
return
}
}
}()

time.Sleep(time.Second * 3)
helpers.DisableProxy("redial", t)

go func() {
time.Sleep(time.Second * 2)
t.Run("PushPipelineWhileRedialing-1", helpers.PushToPipe("test-1", false, "127.0.0.1:6001"))
t.Run("PushPipelineWhileRedialing-2", helpers.PushToPipe("test-2", false, "127.0.0.1:6001"))
}()

time.Sleep(time.Second * 5)
helpers.EnableProxy("redial", t)
time.Sleep(time.Second * 2)

t.Run("PushPipelineWhileRedialing-1", helpers.PushToPipe("test-1", false, "127.0.0.1:6001"))
t.Run("PushPipelineWhileRedialing-2", helpers.PushToPipe("test-2", false, "127.0.0.1:6001"))

time.Sleep(time.Second * 10)
helpers.DestroyPipelines("127.0.0.1:6001", "test-1", "test-2")

stopCh <- struct{}{}
wg.Wait()
}
Copy link

Choose a reason for hiding this comment

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

The test TestDurabilityBeanstalk is well structured and covers a good range of scenarios. However, there are some areas that could be improved for better maintainability and readability.

  1. The use of time.Sleep() to wait for certain operations or conditions can lead to flaky tests if the operation takes longer than expected. It would be better to use some form of synchronization or polling to wait for the condition to be met.

  2. The error handling within the goroutine (lines 74-99) could be simplified. Currently, the same error handling code is repeated three times. Consider refactoring this into a separate function.

  3. The test cases "PushPipelineWhileRedialing-1" and "PushPipelineWhileRedialing-2" are run twice with the same parameters (lines 106-107 and 114-115). If the intention is to repeat the same test under different conditions, it would be clearer to encapsulate these conditions within the test case itself, rather than relying on the state of the system at the time the test case is run.

  4. The test cleanup (line 118) should ideally be done in a defer statement immediately after the resources are created. This ensures that the cleanup is always performed, even if the test fails or panics before reaching the cleanup code.

Here's an example of how you might refactor the error handling:

func handleError(t *testing.T, cont *endure.Container, err error) {
    assert.FailNow(t, "error", err.Error())
    stopErr := cont.Stop()
    if stopErr != nil {
        assert.FailNow(t, "error", stopErr.Error())
    }
}

And then in your goroutine:

go func() {
    defer wg.Done()
    for {
        select {
        case e := <-ch:
            handleError(t, cont, e.Error)
        case <-sig:
            handleError(t, cont, nil)
            return
        case <-stopCh:
            // timeout
            handleError(t, cont, nil)
            return
        }
    }
}()

Comment on lines +165 to +175
func EnableProxy(name string, t *testing.T) {
buf := new(bytes.Buffer)
buf.WriteString(`{"enabled":true}`)

resp, err := http.Post("http://127.0.0.1:8474/proxies/"+name, "application/json", buf) //nolint:noctx
require.NoError(t, err)
require.Equal(t, 200, resp.StatusCode)
if resp.Body != nil {
_ = resp.Body.Close()
}
}
Copy link

Choose a reason for hiding this comment

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

This function enables a Toxiproxy proxy by sending an HTTP POST request with the payload {"enabled":true}. It asserts that no error occurred during the request and that the response status code is 200. If the response body is not nil, it is closed. The hardcoded URL and payload could be moved to constants or configuration files for better maintainability.

Comment on lines +177 to +187
func DisableProxy(name string, t *testing.T) {
buf := new(bytes.Buffer)
buf.WriteString(`{"enabled":false}`)

resp, err := http.Post("http://127.0.0.1:8474/proxies/"+name, "application/json", buf) //nolint:noctx
require.NoError(t, err)
require.Equal(t, 200, resp.StatusCode)
if resp.Body != nil {
_ = resp.Body.Close()
}
}
Copy link

Choose a reason for hiding this comment

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

This function disables a Toxiproxy proxy by sending an HTTP POST request with the payload {"enabled":false}. It asserts that no error occurred during the request and that the response status code is 200. If the response body is not nil, it is closed. The hardcoded URL and payload could be moved to constants or configuration files for better maintainability.

Comment on lines +189 to +203
func DeleteProxy(name string, t *testing.T) {
client := &http.Client{}

req, err := http.NewRequest(http.MethodDelete, "http://127.0.0.1:8474/proxies/"+name, nil) //nolint:noctx
require.NoError(t, err)

resp, err := client.Do(req)
require.NoError(t, err)

require.NoError(t, err)
require.Equal(t, 204, resp.StatusCode)
if resp.Body != nil {
_ = resp.Body.Close()
}
}
Copy link

Choose a reason for hiding this comment

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

This function deletes a Toxiproxy proxy by sending an HTTP DELETE request. It asserts that no error occurred during the request and that the response status code is 204. If the response body is not nil, it is closed. The hardcoded URL could be moved to constants or configuration files for better maintainability.

Signed-off-by: Valery Piashchynski <[email protected]>
@rustatian rustatian merged commit 9db09c0 into master Sep 26, 2023
6 of 7 checks passed
@rustatian rustatian deleted the feature/durability-tests branch September 26, 2023 11:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant