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

Improve the UT coverage for portcache #4284

Merged
merged 1 commit into from
Dec 8, 2022

Conversation

jainpulkit22
Copy link
Contributor

@jainpulkit22 jainpulkit22 commented Oct 12, 2022

Added unit test for pkg/agent/nodeportlocal/portcahce package.

For #4142

Signed-off-by: Pulkit Jain jainpu@vmware.com

@codecov
Copy link

codecov bot commented Oct 12, 2022

Codecov Report

Merging #4284 (2686845) into main (d9b2e37) will increase coverage by 0.84%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #4284      +/-   ##
==========================================
+ Coverage   64.52%   65.36%   +0.84%     
==========================================
  Files         402      402              
  Lines       57238    57238              
==========================================
+ Hits        36932    37416     +484     
+ Misses      17594    17117     -477     
+ Partials     2712     2705       -7     
Flag Coverage Δ
integration-tests 34.66% <ø> (-0.06%) ⬇️
kind-e2e-tests 46.32% <ø> (+5.00%) ⬆️
unit-tests 51.04% <ø> (+0.13%) ⬆️
Impacted Files Coverage Δ
...g/agent/apiserver/handlers/featuregates/handler.go 4.54% <0.00%> (-77.28%) ⬇️
pkg/support/dump_others.go 0.00% <0.00%> (-44.74%) ⬇️
...g/agent/apiserver/handlers/addressgroup/handler.go 5.00% <0.00%> (-35.00%) ⬇️
pkg/agent/apiserver/handlers/agentinfo/handler.go 40.00% <0.00%> (-31.12%) ⬇️
...agent/controller/traceflow/traceflow_controller.go 53.57% <0.00%> (-19.39%) ⬇️
pkg/ipfix/ipfix_process.go 81.25% <0.00%> (-18.75%) ⬇️
pkg/agent/controller/networkpolicy/reject.go 60.59% <0.00%> (-12.32%) ⬇️
pkg/agent/util/iptables/iptables.go 39.37% <0.00%> (-10.89%) ⬇️
pkg/agent/apiserver/handlers/multicast/handler.go 69.76% <0.00%> (-9.31%) ⬇️
pkg/agent/apiserver/apiserver.go 71.27% <0.00%> (-5.32%) ⬇️
... and 60 more

@luolanzone luolanzone mentioned this pull request Oct 13, 2022
37 tasks
@jainpulkit22 jainpulkit22 marked this pull request as ready for review October 13, 2022 03:49
@jainpulkit22 jainpulkit22 marked this pull request as draft October 13, 2022 04:17
@jainpulkit22 jainpulkit22 force-pushed the nodeportlocal-unit-test-coverage branch from 6e208dd to f98c6b8 Compare October 13, 2022 05:43
@jainpulkit22 jainpulkit22 force-pushed the nodeportlocal-unit-test-coverage branch 2 times, most recently from 40f41ad to 0071fcb Compare October 18, 2022 12:37
@jainpulkit22 jainpulkit22 marked this pull request as ready for review October 18, 2022 12:38
@jainpulkit22 jainpulkit22 changed the title Improve the unit test coverage for portcache Improve the UT coverage for portcache Oct 18, 2022
@jainpulkit22 jainpulkit22 force-pushed the nodeportlocal-unit-test-coverage branch 2 times, most recently from e781b7b to 51039c4 Compare October 21, 2022 04:52
portTable := newPortTable(mockIPTables, mockPortOpener)
podIP := "10.0.0.1"

portTable.DeleteRule(podIP, 1001, "tcp")
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the point to call the function without checking anything? The main purpose of unit test is to verify that the function works as we expected. You should check the returned error and comparing it.
I think you can try to call portTable.addPortTableCache() to add a few data on the cache, then test the function with the cache.

Copy link
Member

Choose a reason for hiding this comment

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

+1

mockIPTables.EXPECT().AddRule(nodePort2, podIP, 1002, "udp")

syncedCh := make(chan struct{})
const timeout = 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.

You can define this const on line 32

endPort = 65000
)

func newPortTable(mockIPTables rules.PodPortRules, mockPortOpener LocalPortOpener) *PortTable {
Copy link
Member

Choose a reason for hiding this comment

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

windows doesn't have IPTable, which may be the reason why the type is named generically. Using mockIPTables as argument name doesn't make sense.

func TestRestoreRules(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockIPTables := rulestesting.NewMockPodPortRules(mockCtrl)
Copy link
Member

Choose a reason for hiding this comment

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

ditto

Comment on lines 89 to 96
select {
case <-syncedCh:
break
case <-time.After(timeout):
// this will not kill the goroutine created by RestoreRules,
// which should be acceptable.
t.Fatalf("Rule restoration not complete after %v", timeout)
}
Copy link
Member

Choose a reason for hiding this comment

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

RestoreRules's windows version has nothing to do with goroutine, this shouldn't be copied.

portTable := newPortTable(mockIPTables, mockPortOpener)
podIP := "10.0.0.1"

portTable.DeleteRule(podIP, 1001, "tcp")
Copy link
Member

Choose a reason for hiding this comment

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

+1

@luolanzone luolanzone added this to the Antrea v1.10 release milestone Oct 27, 2022
@jainpulkit22 jainpulkit22 force-pushed the nodeportlocal-unit-test-coverage branch 2 times, most recently from 3163eaa to c6b39cc Compare November 23, 2022 14:24
@jainpulkit22 jainpulkit22 marked this pull request as draft November 23, 2022 14:25
@jainpulkit22 jainpulkit22 force-pushed the nodeportlocal-unit-test-coverage branch 8 times, most recently from e39d51d to a1aaa1c Compare November 28, 2022 06:22
} else {
mockPortRules.EXPECT().AddRule(tc.nodePort, tc.podIP, tc.podPort, tc.protocol)
nodePort, err := portTable.AddRule(tc.podIP, tc.podPort, tc.protocol)
assert.NoError(t, err)
Copy link
Contributor

Choose a reason for hiding this comment

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

require.NoError(t, err) is a good practice to ensure that the test will abort earlier.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But in this case there are no follow-up function calls that will panic, so isn't this fine to use assert here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

also the rest of the cases for the current test are skipped if we use require instead of assert.

Copy link
Contributor

Choose a reason for hiding this comment

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

That is expected, I think there is no point to check the other values when there is an unexpected error.

startPort = 61000
endPort = 65000
)

Copy link
Contributor

Choose a reason for hiding this comment

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

Functions like addRuleforFreePort and addRuleForPort needs to called from test file by mocking the top level function and hence internal functions will be considered for percentage UT coverage, this can substantialy increase the coverage, the UT tool does not consider the coverage if the functions are internal, Suggest to follow this approach to increase UT coverage.

Copy link
Contributor

@rajnkamr rajnkamr left a comment

Choose a reason for hiding this comment

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

Functions like addRuleforFreePort and addRuleForPort needs to called from test file by mocking the top level function and hence internal functions will be considered for percentage UT coverage, this can substantialy increase the coverage, the UT tool does not consider the coverage if the functions are internal, Suggest to follow this approach to increase UT coverage.

@jainpulkit22 jainpulkit22 force-pushed the nodeportlocal-unit-test-coverage branch from 222730c to ff7901a Compare November 29, 2022 06:11
@jainpulkit22 jainpulkit22 force-pushed the nodeportlocal-unit-test-coverage branch 3 times, most recently from b8f9a0c to 895204a Compare November 29, 2022 10:06
Comment on lines 33 to 36
const (
startPort = 61000
endPort = 65000
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can these variables and newPortTable be shared for linux and windows test? I didn't see any differences.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes they can be, but we do not have any shared file for test purpose, or you want me to declare these variables in the actual code file.

Comment on lines 59 to 61
podIP := "10.0.0.1"
nodePort1 := startPort
nodePort2 := startPort + 1
Copy link
Contributor

Choose a reason for hiding this comment

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

You probably can also define shared test data for these.

Comment on lines 152 to 153
podIP: "10.0.0.1",
podPort: 1001,
Copy link
Contributor

@luolanzone luolanzone Nov 30, 2022

Choose a reason for hiding this comment

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

I suppose these two fields can be removed if their values are all the same in all cases. If they should change to cover more, then you may need to add more different cases.

@jainpulkit22 jainpulkit22 force-pushed the nodeportlocal-unit-test-coverage branch from 895204a to ffa209b Compare December 1, 2022 11:34
@luolanzone luolanzone removed this from the Antrea v1.10 release milestone Dec 5, 2022
Copy link
Contributor

@luolanzone luolanzone left a comment

Choose a reason for hiding this comment

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

LGTM overall, two nits.

luolanzone
luolanzone previously approved these changes Dec 7, 2022
Copy link
Contributor

@luolanzone luolanzone left a comment

Choose a reason for hiding this comment

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

LGTM

@@ -0,0 +1,44 @@
// Copyright 2022 Antrea Authors
Copy link
Member

Choose a reason for hiding this comment

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

Not having test.go suffix will make the file be compiled into antrea-agent binary, increasing its size unnecessarily. Normally the platform-generic code could be put under foo_test.go, then both foo_linux_test.go and foo_windows_test.go can use it. We should rename the current port_table_test.go to port_table_linux_test.go if it's supposed to run on linux only or port_table_other_test.go.

Comment on lines 102 to 106
if tc.testForPod {
err = portTable.DeleteRule(podIP, 1001, "tcp")
} else {
err = portTable.DeleteRulesForPod(podIP)
}
Copy link
Member

Choose a reason for hiding this comment

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

  1. When testForPod is true, it tests DeleteRule, which looks confusing.
  2. It's actually not common to test two different functions in one test, orginazing them as table driven style, which is usually about expected input and output for same function. To share code for multiple tests, extracting common code to a shared function is more common.
  3. However, I think the point of DeleteRulesForPod is it can delete all rules for the specific pod IP, unlike DeleteRule can only delete one specified rule. So an appropriate test for the former is to construct multiple rules first, then make sure a single call can clean up all of them.

Comment on lines 150 to 163
for _, tc := range tcs {
t.Run(tc.name, func(t *testing.T) {
if tc.expectedErr == "" {
mockPortRules.EXPECT().AddRule(tc.nodePort, podIP, podPort, tc.protocol)
}
nodePort, err := portTable.AddRule(podIP, podPort, tc.protocol)
if tc.expectedErr != "" {
assert.ErrorContains(t, err, tc.expectedErr)
} else {
require.NoError(t, err)
assert.Equal(t, tc.nodePort, nodePort)
}
})
}
Copy link
Member

Choose a reason for hiding this comment

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

table driven test's cases should be individual, so it's easy to add new cases and adjust existing ones with worrying about the others, and it makes it possible to run specific sub test only.
I assume in this test the 2nd subtest relies on the 1st one.
It should just do it sequentially to make the dependency clear:

mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockPortRules := rulestesting.NewMockPodPortRules(mockCtrl)
mockPortOpener := portcachetesting.NewMockLocalPortOpener(mockCtrl)
portTable := newPortTable(mockPortRules, mockPortOpener)
podPort := 1001

// Adding the rule the first time should succeed.
mockPortRules.EXPECT().AddRule(tc.nodePort, podIP, podPort, tc.protocol)
gotNodePort, err := portTable.AddRule(podIP, podPort, tc.protocol)
require.NoError(t, err)
assert.Equal(t, startPort, gotNodePort)

// Add the same rule the second time should fail.
_, err := portTable.AddRule(podIP, podPort, tc.protocol)
assert.ErrorContains(t, err, "existing Windows Nodeport entry for")

@@ -0,0 +1,44 @@
// Copyright 2022 Antrea Authors
Copy link
Member

Choose a reason for hiding this comment

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

It's not common to have a test file whose name's prefix doesn't map to a file.
Since this is for the test code of port_table.go, it could just be named port_table_test.go.

Signed-off-by: Pulkit Jain <jainpu@vmware.com>
@jainpulkit22 jainpulkit22 force-pushed the nodeportlocal-unit-test-coverage branch from 502f590 to 2686845 Compare December 8, 2022 14:36
Copy link
Member

@tnqn tnqn left a comment

Choose a reason for hiding this comment

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

LGTM

@tnqn
Copy link
Member

tnqn commented Dec 8, 2022

/skip-all

@tnqn tnqn merged commit a9fd9d2 into antrea-io:main Dec 8, 2022
GraysonWu pushed a commit to GraysonWu/antrea that referenced this pull request Jan 27, 2023
Signed-off-by: Pulkit Jain <jainpu@vmware.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants