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

Add tests for runtime manager #1555

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

zedGGs
Copy link

@zedGGs zedGGs commented Feb 9, 2024

Proposed changes

Problem: Missing tests on runtime manager

Im adding this init pr with few tests, if this goes well I can add another pr with more tests

gentle ping for @sjberman

Solution: Added tests and tested locally

Testing: running go test locally

optional: additional questions to clarify mocking and provide more details

Is practice for mocking runtime manager, more to use current usage with:
mgr = NewManagerImpl(&ngxclient.NginxClient{}, nil, logr.New(GinkgoLogr.GetSink()))

or I can use already created mock from runtimefakes:
runtimefakes.FakeManager as mocked struct, even tho its mocked interface ?

or its required to actually mock MetricsCollector in runtimefakes by creating runtimefakes.FakeMetricsCollector with counterfeiter and then use that one, in
NewManagerImpl(&ngxclient.NginxClient{}, &runtmefakes.FakeMetricCollector{}, logr.New(GinkgoLogr.GetSink()))

or in

mockedManager := &runtimefakes.FakeManager{}

any advice on this is appreciated a lot, thank you in advance

Closes #1498

Checklist

Before creating a PR, run through this checklist and mark each as complete.

  • I have read the CONTRIBUTING doc
  • I have added tests that prove my fix is effective or that my feature works
  • I have checked that all unit tests pass after adding my changes
  • I have updated necessary documentation
  • I have rebased my branch onto main
  • I will ensure my PR is targeting the main branch and pulling from my branch from my own fork

@zedGGs zedGGs requested a review from a team as a code owner February 9, 2024 12:34
@github-actions github-actions bot added the tests Pull requests that update tests label Feb 9, 2024
@zedGGs zedGGs force-pushed the test/add-runtime-manager-tests branch from ec34013 to 99997c4 Compare February 9, 2024 12:58
@sjberman
Copy link
Contributor

sjberman commented Feb 9, 2024

@zedGGs To answer your question about mocking, one of the goals of this work is to test out the ManagerImpl functions in manager.go. So this means we'll need to use the real ManagerImpl implementation, but be able to mock out the components that it uses, so we ensure we're just testing the ManagerImpl.

@zedGGs
Copy link
Author

zedGGs commented Feb 10, 2024

@sjberman sounds good,
thank you for the feedback and review, Im going to proceed accordingly

@zedGGs zedGGs requested a review from sjberman February 16, 2024 19:36
@zedGGs
Copy link
Author

zedGGs commented Feb 16, 2024

@sjberman apologies for not being on time with an update,

current test cases for ManagerImpl are for situations where theres an error,
I can say I had little issues to properly mock correct upstreams on nginx client, so I have not added these test cases,
even tho I tried to do this, I can say I actually don't know how this works, any advice is appreciated

thank you in advance !

if you want you can take current changes and I can add separated pr for good test cases,

issue happens to be:

failed to update servers of unknown upstream: failed to get the HTTP servers of upstream unknown: failed to get http/upstreams/unknown/servers: Get "http://10.0.0.1:80/9/http/upstreams/unknown/servers": context deadline exceeded (Client.Timeout exceeded while awaiting headers)

			serversMock = ngxclient.UpstreamServer{
				ID:          1,
				Server:      "10.0.0.1:80",
				MaxConns:    &MaxConnsMock,
				MaxFails:    &MaxFailsMock,
				FailTimeout: "test",
				SlowStart:   "test",
				Route:       "test",
				Backup:      &BackupMock,
				Down:        &DownMock,
				Drain:       false,
				Weight:      &WeightMock,
				Service:     "",
			}

with ngxclient.NewNginxClient("10.0.0.1:80", client.WithHTTPClient(httpClient))

@zedGGs zedGGs force-pushed the test/add-runtime-manager-tests branch from b84583c to b36adc6 Compare February 16, 2024 19:56
@sjberman
Copy link
Contributor

@zedGGs Thanks for the update. The issue you're seeing is that the nginx client is attempting to reach a real server, and fails. For unit tests we obviously do not want to use a real server. This means we probably need to create interfaces in https://github.com/nginxinc/nginx-plus-go-client, so we can provide a mock client in our own unit tests that won't try to contact a real server.

@zedGGs zedGGs requested a review from sjberman February 20, 2024 06:09
@zedGGs
Copy link
Author

zedGGs commented Feb 20, 2024

@sjberman here's an update, I have added NginxPlusClient to use UpdateHTTPServers and GetUpstreams since they are only being used currently,
can add more improvements in test overall if you think something can be better

thanks

@zedGGs zedGGs force-pushed the test/add-runtime-manager-tests branch from 4663750 to 0b42d66 Compare February 20, 2024 06:21
@sjberman
Copy link
Contributor

It would be nice if we could also find a way to test the Reload() function. May require temporary files and another client mock.

@zedGGs
Copy link
Author

zedGGs commented Feb 21, 2024

@kate-osborn sure, I am going to try add tests for that too
thanks for feedback !!

@zedGGs zedGGs force-pushed the test/add-runtime-manager-tests branch 2 times, most recently from f027f15 to dd4a219 Compare February 26, 2024 11:05
@zedGGs zedGGs force-pushed the test/add-runtime-manager-tests branch from dd4a219 to 724f615 Compare February 26, 2024 11:07
Comment on lines 78 to 79
err := manager.Reload(context.Background(), 1)
Expect(err).To(BeNil())
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
err := manager.Reload(context.Background(), 1)
Expect(err).To(BeNil())
Expect(manager.Reload(context.Background(), 1)).To(Succeed())

I would also verify that each of the other interface functions were called (WaitForCorrectVersionCallCount, SyscallKillCallCount, etc)

Copy link
Author

Choose a reason for hiding this comment

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

will do, thats good idea

Comment on lines 213 to 214
nil,
nil,
Copy link
Contributor

Choose a reason for hiding this comment

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

These need to be initialized for the real thing.

Copy link
Author

Choose a reason for hiding this comment

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

@sjberman btw to update this properly I think I need for ProcessHandler interface, add ProcessHandlerImpl, if this is even good approach,

thank you !

type processHandler interface {
FindMainProcess(ctx context.Context, checkFile CheckFileFunc, readFile ReadFileFunc, timeout time.Duration) (int, error)
ReadFile(file string) ([]byte, error)
SysCallKill(pid int, signum syscall.Signal) error
Copy link
Contributor

Choose a reason for hiding this comment

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

I would just call this Kill.

Copy link
Author

Choose a reason for hiding this comment

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

sounds good

logger logr.Logger
process processHandler
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd call the variable processHandler as well

Copy link
Author

Choose a reason for hiding this comment

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

sure will do that

Comment on lines 10 to 11
"github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/nginx/runtime"
"github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/nginx/runtime/runtimefakes"
Copy link
Contributor

Choose a reason for hiding this comment

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

Separate these internal imports into a third category below the third-party imports.

Copy link
Author

Choose a reason for hiding this comment

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

will do

)

var _ = Describe("NGINX Runtime Manager", func() {
var _ = Describe("NGINX Runtime Manager", Ordered, func() {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't believe these tests need to be Ordered, do they?

Copy link
Author

Choose a reason for hiding this comment

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

when I have used BeforeAll, I was required to use Ordered, but if I use BeforeEach, then its not required, if you agree on that I can make updates

Copy link
Contributor

Choose a reason for hiding this comment

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

BeforeEach is fine in this case

Copy link
Author

Choose a reason for hiding this comment

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

awesome, going to proceed accordingly

Comment on lines 47 to 60
upstreamServer = ngxclient.UpstreamServer{
ID: 1,
Server: "10.0.0.1:80",
MaxConns: &MaxConnsMock,
MaxFails: &MaxFailsMock,
FailTimeout: "test",
SlowStart: "test",
Route: "test",
Backup: &BackupMock,
Down: &DownMock,
Drain: false,
Weight: &WeightMock,
Service: "test",
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Are these fields actually necessary to fill out for the test? I'm assuming we could just use an empty list of servers when calling the API function

Copy link
Author

Choose a reason for hiding this comment

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

seems to be good without all of this stuff, so I will not fill these fields

Comment on lines 115 to 117
err := manager.UpdateHTTPServers("test", upstreamServers)

Expect(err).To(BeNil())
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
err := manager.UpdateHTTPServers("test", upstreamServers)
Expect(err).To(BeNil())
Expect(manager.UpdateHTTPServers("test", upstreamServers)).To(Succeed())

Copy link
Author

Choose a reason for hiding this comment

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

thanks for suggestion Im going to add an update


//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . processHandler

type processHandler interface {
Copy link
Author

Choose a reason for hiding this comment

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

gentle ping @sjberman do you want me to add processHandlerImpl ? so I can use that outside, but then
func(p *ProcessHandlerImpl) FindMainProcess gets also updated, if this is even good approach, the goal is to cover these nil, nil that I used for real implementation

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, that would be necessary to create an implementation.

Copy link
Contributor

This PR is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 14 days.

@github-actions github-actions bot added the stale Pull requests/issues with no activity label Mar 12, 2024
@zedGGs zedGGs requested a review from sjberman March 12, 2024 18:46
@sjberman sjberman removed the stale Pull requests/issues with no activity label Mar 12, 2024
@@ -212,6 +213,8 @@ func StartManager(cfg config.Config) error {
ngxPlusClient,
ngxruntimeCollector,
cfg.Logger.WithName("nginxRuntimeManager"),
&ngxruntime.ProcessHandlerImpl{},
ngxruntime.NewVerifyClient(1*time.Second),
Copy link
Contributor

Choose a reason for hiding this comment

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

This timeout should be the same as nginxReloadTimeout in the runtime manager. Let's export and use it.

Copy link
Author

Choose a reason for hiding this comment

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

sure

@@ -133,7 +133,7 @@ func StartManager(cfg config.Config) error {
}

// Ensure NGINX is running before registering metrics & starting the manager.
if err := ngxruntime.EnsureNginxRunning(ctx); err != nil {
if err := ngxruntime.EnsureNginxRunning(ctx, &ngxruntime.ProcessHandlerImpl{}); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think I'd rather initialize a single processHandler, make the EnsureNginxRunning function a method for that object, and then reuse the processHandler in the runtime manager initialization.

@@ -144,6 +144,7 @@ func StartManager(cfg config.Config) error {

var ngxPlusClient *ngxclient.NginxClient
var usageSecret *usage.Secret
//var processHandler *ngxruntime.ProcessHandler
Copy link
Contributor

Choose a reason for hiding this comment

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

unneeded line

Copy link
Author

Choose a reason for hiding this comment

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

sure, will add an update

@mpstefan mpstefan added this to the v1.3.0 milestone Mar 20, 2024
Copy link
Contributor

github-actions bot commented Apr 4, 2024

This PR is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 14 days.

@github-actions github-actions bot added the stale Pull requests/issues with no activity label Apr 4, 2024
Copy link
Contributor

This PR was closed because it has been stalled for 14 days with no activity.

@github-actions github-actions bot closed this Apr 18, 2024
@mpstefan
Copy link
Collaborator

Reopening after discussion with Zedd!

@mpstefan mpstefan reopened this Apr 22, 2024
@sjberman sjberman removed the stale Pull requests/issues with no activity label Apr 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
community tests Pull requests that update tests
Projects
Status: External Pull Requests
Development

Successfully merging this pull request may close these issues.

Add unit tests for nginx runtime manager
5 participants