diff options
Diffstat (limited to 'pkg/tcpip/stack/nud_test.go')
-rw-r--r-- | pkg/tcpip/stack/nud_test.go | 816 |
1 files changed, 0 insertions, 816 deletions
diff --git a/pkg/tcpip/stack/nud_test.go b/pkg/tcpip/stack/nud_test.go deleted file mode 100644 index 1aeb2f8a5..000000000 --- a/pkg/tcpip/stack/nud_test.go +++ /dev/null @@ -1,816 +0,0 @@ -// Copyright 2020 The gVisor Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package stack_test - -import ( - "math" - "math/rand" - "testing" - "time" - - "github.com/google/go-cmp/cmp" - "gvisor.dev/gvisor/pkg/tcpip" - "gvisor.dev/gvisor/pkg/tcpip/faketime" - "gvisor.dev/gvisor/pkg/tcpip/link/channel" - "gvisor.dev/gvisor/pkg/tcpip/network/ipv6" - "gvisor.dev/gvisor/pkg/tcpip/stack" -) - -const ( - defaultBaseReachableTime = 30 * time.Second - minimumBaseReachableTime = time.Millisecond - defaultMinRandomFactor = 0.5 - defaultMaxRandomFactor = 1.5 - defaultRetransmitTimer = time.Second - minimumRetransmitTimer = time.Millisecond - defaultDelayFirstProbeTime = 5 * time.Second - defaultMaxMulticastProbes = 3 - defaultMaxUnicastProbes = 3 - - defaultFakeRandomNum = 0.5 -) - -// fakeRand is a deterministic random number generator. -type fakeRand struct { - num float32 -} - -var _ rand.Source = (*fakeRand)(nil) - -func (f *fakeRand) Int63() int64 { - return int64(f.num * float32(1<<63)) -} - -func (*fakeRand) Seed(int64) {} - -func TestNUDFunctions(t *testing.T) { - const nicID = 1 - - tests := []struct { - name string - nicID tcpip.NICID - netProtoFactory []stack.NetworkProtocolFactory - extraLinkCapabilities stack.LinkEndpointCapabilities - expectedErr tcpip.Error - }{ - { - name: "Invalid NICID", - nicID: nicID + 1, - netProtoFactory: []stack.NetworkProtocolFactory{ipv6.NewProtocol}, - extraLinkCapabilities: stack.CapabilityResolutionRequired, - expectedErr: &tcpip.ErrUnknownNICID{}, - }, - { - name: "No network protocol", - nicID: nicID, - expectedErr: &tcpip.ErrNotSupported{}, - }, - { - name: "With IPv6", - nicID: nicID, - netProtoFactory: []stack.NetworkProtocolFactory{ipv6.NewProtocol}, - expectedErr: &tcpip.ErrNotSupported{}, - }, - { - name: "With resolution capability", - nicID: nicID, - extraLinkCapabilities: stack.CapabilityResolutionRequired, - expectedErr: &tcpip.ErrNotSupported{}, - }, - { - name: "With IPv6 and resolution capability", - nicID: nicID, - netProtoFactory: []stack.NetworkProtocolFactory{ipv6.NewProtocol}, - extraLinkCapabilities: stack.CapabilityResolutionRequired, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - clock := faketime.NewManualClock() - s := stack.New(stack.Options{ - NUDConfigs: stack.DefaultNUDConfigurations(), - NetworkProtocols: test.netProtoFactory, - Clock: clock, - }) - - e := channel.New(0, 0, linkAddr1) - e.LinkEPCapabilities &^= stack.CapabilityResolutionRequired - e.LinkEPCapabilities |= test.extraLinkCapabilities - - if err := s.CreateNIC(nicID, e); err != nil { - t.Fatalf("CreateNIC(%d, _) = %s", nicID, err) - } - - configs := stack.DefaultNUDConfigurations() - configs.BaseReachableTime = time.Hour - - { - err := s.SetNUDConfigurations(test.nicID, ipv6.ProtocolNumber, configs) - if diff := cmp.Diff(test.expectedErr, err); diff != "" { - t.Errorf("s.SetNUDConfigurations(%d, %d, _) error mismatch (-want +got):\n%s", test.nicID, ipv6.ProtocolNumber, diff) - } - } - - { - gotConfigs, err := s.NUDConfigurations(test.nicID, ipv6.ProtocolNumber) - if diff := cmp.Diff(test.expectedErr, err); diff != "" { - t.Errorf("s.NUDConfigurations(%d, %d) error mismatch (-want +got):\n%s", test.nicID, ipv6.ProtocolNumber, diff) - } else if test.expectedErr == nil { - if diff := cmp.Diff(configs, gotConfigs); diff != "" { - t.Errorf("got configs mismatch (-want +got):\n%s", diff) - } - } - } - - for _, addr := range []tcpip.Address{llAddr1, llAddr2} { - { - err := s.AddStaticNeighbor(test.nicID, ipv6.ProtocolNumber, addr, linkAddr1) - if diff := cmp.Diff(test.expectedErr, err); diff != "" { - t.Errorf("s.AddStaticNeighbor(%d, %d, %s, %s) error mismatch (-want +got):\n%s", test.nicID, ipv6.ProtocolNumber, addr, linkAddr1, diff) - } - } - } - - { - wantErr := test.expectedErr - for i := 0; i < 2; i++ { - { - err := s.RemoveNeighbor(test.nicID, ipv6.ProtocolNumber, llAddr1) - if diff := cmp.Diff(wantErr, err); diff != "" { - t.Errorf("s.RemoveNeighbor(%d, %d, '') error mismatch (-want +got):\n%s", test.nicID, ipv6.ProtocolNumber, diff) - } - } - - if test.expectedErr != nil { - break - } - - // Removing a neighbor that does not exist should give us a bad address - // error. - wantErr = &tcpip.ErrBadAddress{} - } - } - - { - neighbors, err := s.Neighbors(test.nicID, ipv6.ProtocolNumber) - if diff := cmp.Diff(test.expectedErr, err); diff != "" { - t.Errorf("s.Neigbors(%d, %d) error mismatch (-want +got):\n%s", test.nicID, ipv6.ProtocolNumber, diff) - } else if test.expectedErr == nil { - if diff := cmp.Diff( - []stack.NeighborEntry{{Addr: llAddr2, LinkAddr: linkAddr1, State: stack.Static, UpdatedAt: clock.Now()}}, - neighbors, - ); diff != "" { - t.Errorf("neighbors mismatch (-want +got):\n%s", diff) - } - } - } - - { - err := s.ClearNeighbors(test.nicID, ipv6.ProtocolNumber) - if diff := cmp.Diff(test.expectedErr, err); diff != "" { - t.Errorf("s.ClearNeigbors(%d, %d) error mismatch (-want +got):\n%s", test.nicID, ipv6.ProtocolNumber, diff) - } else if test.expectedErr == nil { - if neighbors, err := s.Neighbors(test.nicID, ipv6.ProtocolNumber); err != nil { - t.Errorf("s.Neighbors(%d, %d): %s", test.nicID, ipv6.ProtocolNumber, err) - } else if len(neighbors) != 0 { - t.Errorf("got len(neighbors) = %d, want = 0; neighbors = %#v", len(neighbors), neighbors) - } - } - } - }) - } -} - -func TestDefaultNUDConfigurations(t *testing.T) { - const nicID = 1 - - e := channel.New(0, 1280, linkAddr1) - e.LinkEPCapabilities |= stack.CapabilityResolutionRequired - - s := stack.New(stack.Options{ - // A neighbor cache is required to store NUDConfigurations. The networking - // stack will only allocate neighbor caches if a protocol providing link - // address resolution is specified (e.g. ARP or IPv6). - NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocol}, - NUDConfigs: stack.DefaultNUDConfigurations(), - }) - if err := s.CreateNIC(nicID, e); err != nil { - t.Fatalf("CreateNIC(%d, _) = %s", nicID, err) - } - c, err := s.NUDConfigurations(nicID, ipv6.ProtocolNumber) - if err != nil { - t.Fatalf("got stack.NUDConfigurations(%d, %d) = %s", nicID, ipv6.ProtocolNumber, err) - } - if got, want := c, stack.DefaultNUDConfigurations(); got != want { - t.Errorf("got stack.NUDConfigurations(%d, %d) = %+v, want = %+v", nicID, ipv6.ProtocolNumber, got, want) - } -} - -func TestNUDConfigurationsBaseReachableTime(t *testing.T) { - tests := []struct { - name string - baseReachableTime time.Duration - want time.Duration - }{ - // Invalid cases - { - name: "EqualToZero", - baseReachableTime: 0, - want: defaultBaseReachableTime, - }, - // Valid cases - { - name: "MoreThanZero", - baseReachableTime: time.Millisecond, - want: time.Millisecond, - }, - { - name: "MoreThanDefaultBaseReachableTime", - baseReachableTime: 2 * defaultBaseReachableTime, - want: 2 * defaultBaseReachableTime, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - const nicID = 1 - - c := stack.DefaultNUDConfigurations() - c.BaseReachableTime = test.baseReachableTime - - e := channel.New(0, 1280, linkAddr1) - e.LinkEPCapabilities |= stack.CapabilityResolutionRequired - - s := stack.New(stack.Options{ - // A neighbor cache is required to store NUDConfigurations. The - // networking stack will only allocate neighbor caches if a protocol - // providing link address resolution is specified (e.g. ARP or IPv6). - NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocol}, - NUDConfigs: c, - }) - if err := s.CreateNIC(nicID, e); err != nil { - t.Fatalf("CreateNIC(%d, _) = %s", nicID, err) - } - sc, err := s.NUDConfigurations(nicID, ipv6.ProtocolNumber) - if err != nil { - t.Fatalf("got stack.NUDConfigurations(%d, %d) = %s", nicID, ipv6.ProtocolNumber, err) - } - if got := sc.BaseReachableTime; got != test.want { - t.Errorf("got BaseReachableTime = %q, want = %q", got, test.want) - } - }) - } -} - -func TestNUDConfigurationsMinRandomFactor(t *testing.T) { - tests := []struct { - name string - minRandomFactor float32 - want float32 - }{ - // Invalid cases - { - name: "LessThanZero", - minRandomFactor: -1, - want: defaultMinRandomFactor, - }, - { - name: "EqualToZero", - minRandomFactor: 0, - want: defaultMinRandomFactor, - }, - // Valid cases - { - name: "MoreThanZero", - minRandomFactor: 1, - want: 1, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - const nicID = 1 - - c := stack.DefaultNUDConfigurations() - c.MinRandomFactor = test.minRandomFactor - - e := channel.New(0, 1280, linkAddr1) - e.LinkEPCapabilities |= stack.CapabilityResolutionRequired - - s := stack.New(stack.Options{ - // A neighbor cache is required to store NUDConfigurations. The - // networking stack will only allocate neighbor caches if a protocol - // providing link address resolution is specified (e.g. ARP or IPv6). - NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocol}, - NUDConfigs: c, - }) - if err := s.CreateNIC(nicID, e); err != nil { - t.Fatalf("CreateNIC(%d, _) = %s", nicID, err) - } - sc, err := s.NUDConfigurations(nicID, ipv6.ProtocolNumber) - if err != nil { - t.Fatalf("got stack.NUDConfigurations(%d, %d) = %s", nicID, ipv6.ProtocolNumber, err) - } - if got := sc.MinRandomFactor; got != test.want { - t.Errorf("got MinRandomFactor = %f, want = %f", got, test.want) - } - }) - } -} - -func TestNUDConfigurationsMaxRandomFactor(t *testing.T) { - tests := []struct { - name string - minRandomFactor float32 - maxRandomFactor float32 - want float32 - }{ - // Invalid cases - { - name: "LessThanZero", - minRandomFactor: defaultMinRandomFactor, - maxRandomFactor: -1, - want: defaultMaxRandomFactor, - }, - { - name: "EqualToZero", - minRandomFactor: defaultMinRandomFactor, - maxRandomFactor: 0, - want: defaultMaxRandomFactor, - }, - { - name: "LessThanMinRandomFactor", - minRandomFactor: defaultMinRandomFactor, - maxRandomFactor: defaultMinRandomFactor * 0.99, - want: defaultMaxRandomFactor, - }, - { - name: "MoreThanMinRandomFactorWhenMinRandomFactorIsLargerThanMaxRandomFactorDefault", - minRandomFactor: defaultMaxRandomFactor * 2, - maxRandomFactor: defaultMaxRandomFactor, - want: defaultMaxRandomFactor * 6, - }, - // Valid cases - { - name: "EqualToMinRandomFactor", - minRandomFactor: defaultMinRandomFactor, - maxRandomFactor: defaultMinRandomFactor, - want: defaultMinRandomFactor, - }, - { - name: "MoreThanMinRandomFactor", - minRandomFactor: defaultMinRandomFactor, - maxRandomFactor: defaultMinRandomFactor * 1.1, - want: defaultMinRandomFactor * 1.1, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - const nicID = 1 - - c := stack.DefaultNUDConfigurations() - c.MinRandomFactor = test.minRandomFactor - c.MaxRandomFactor = test.maxRandomFactor - - e := channel.New(0, 1280, linkAddr1) - e.LinkEPCapabilities |= stack.CapabilityResolutionRequired - - s := stack.New(stack.Options{ - // A neighbor cache is required to store NUDConfigurations. The - // networking stack will only allocate neighbor caches if a protocol - // providing link address resolution is specified (e.g. ARP or IPv6). - NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocol}, - NUDConfigs: c, - }) - if err := s.CreateNIC(nicID, e); err != nil { - t.Fatalf("CreateNIC(%d, _) = %s", nicID, err) - } - sc, err := s.NUDConfigurations(nicID, ipv6.ProtocolNumber) - if err != nil { - t.Fatalf("got stack.NUDConfigurations(%d, %d) = %s", nicID, ipv6.ProtocolNumber, err) - } - if got := sc.MaxRandomFactor; got != test.want { - t.Errorf("got MaxRandomFactor = %f, want = %f", got, test.want) - } - }) - } -} - -func TestNUDConfigurationsRetransmitTimer(t *testing.T) { - tests := []struct { - name string - retransmitTimer time.Duration - want time.Duration - }{ - // Invalid cases - { - name: "EqualToZero", - retransmitTimer: 0, - want: defaultRetransmitTimer, - }, - { - name: "LessThanMinimumRetransmitTimer", - retransmitTimer: minimumRetransmitTimer - time.Nanosecond, - want: defaultRetransmitTimer, - }, - // Valid cases - { - name: "EqualToMinimumRetransmitTimer", - retransmitTimer: minimumRetransmitTimer, - want: minimumBaseReachableTime, - }, - { - name: "LargetThanMinimumRetransmitTimer", - retransmitTimer: 2 * minimumBaseReachableTime, - want: 2 * minimumBaseReachableTime, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - const nicID = 1 - - c := stack.DefaultNUDConfigurations() - c.RetransmitTimer = test.retransmitTimer - - e := channel.New(0, 1280, linkAddr1) - e.LinkEPCapabilities |= stack.CapabilityResolutionRequired - - s := stack.New(stack.Options{ - // A neighbor cache is required to store NUDConfigurations. The - // networking stack will only allocate neighbor caches if a protocol - // providing link address resolution is specified (e.g. ARP or IPv6). - NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocol}, - NUDConfigs: c, - }) - if err := s.CreateNIC(nicID, e); err != nil { - t.Fatalf("CreateNIC(%d, _) = %s", nicID, err) - } - sc, err := s.NUDConfigurations(nicID, ipv6.ProtocolNumber) - if err != nil { - t.Fatalf("got stack.NUDConfigurations(%d, %d) = %s", nicID, ipv6.ProtocolNumber, err) - } - if got := sc.RetransmitTimer; got != test.want { - t.Errorf("got RetransmitTimer = %q, want = %q", got, test.want) - } - }) - } -} - -func TestNUDConfigurationsDelayFirstProbeTime(t *testing.T) { - tests := []struct { - name string - delayFirstProbeTime time.Duration - want time.Duration - }{ - // Invalid cases - { - name: "EqualToZero", - delayFirstProbeTime: 0, - want: defaultDelayFirstProbeTime, - }, - // Valid cases - { - name: "MoreThanZero", - delayFirstProbeTime: time.Millisecond, - want: time.Millisecond, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - const nicID = 1 - - c := stack.DefaultNUDConfigurations() - c.DelayFirstProbeTime = test.delayFirstProbeTime - - e := channel.New(0, 1280, linkAddr1) - e.LinkEPCapabilities |= stack.CapabilityResolutionRequired - - s := stack.New(stack.Options{ - // A neighbor cache is required to store NUDConfigurations. The - // networking stack will only allocate neighbor caches if a protocol - // providing link address resolution is specified (e.g. ARP or IPv6). - NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocol}, - NUDConfigs: c, - }) - if err := s.CreateNIC(nicID, e); err != nil { - t.Fatalf("CreateNIC(%d, _) = %s", nicID, err) - } - sc, err := s.NUDConfigurations(nicID, ipv6.ProtocolNumber) - if err != nil { - t.Fatalf("got stack.NUDConfigurations(%d, %d) = %s", nicID, ipv6.ProtocolNumber, err) - } - if got := sc.DelayFirstProbeTime; got != test.want { - t.Errorf("got DelayFirstProbeTime = %q, want = %q", got, test.want) - } - }) - } -} - -func TestNUDConfigurationsMaxMulticastProbes(t *testing.T) { - tests := []struct { - name string - maxMulticastProbes uint32 - want uint32 - }{ - // Invalid cases - { - name: "EqualToZero", - maxMulticastProbes: 0, - want: defaultMaxMulticastProbes, - }, - // Valid cases - { - name: "MoreThanZero", - maxMulticastProbes: 1, - want: 1, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - const nicID = 1 - - c := stack.DefaultNUDConfigurations() - c.MaxMulticastProbes = test.maxMulticastProbes - - e := channel.New(0, 1280, linkAddr1) - e.LinkEPCapabilities |= stack.CapabilityResolutionRequired - - s := stack.New(stack.Options{ - // A neighbor cache is required to store NUDConfigurations. The - // networking stack will only allocate neighbor caches if a protocol - // providing link address resolution is specified (e.g. ARP or IPv6). - NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocol}, - NUDConfigs: c, - }) - if err := s.CreateNIC(nicID, e); err != nil { - t.Fatalf("CreateNIC(%d, _) = %s", nicID, err) - } - sc, err := s.NUDConfigurations(nicID, ipv6.ProtocolNumber) - if err != nil { - t.Fatalf("got stack.NUDConfigurations(%d, %d) = %s", nicID, ipv6.ProtocolNumber, err) - } - if got := sc.MaxMulticastProbes; got != test.want { - t.Errorf("got MaxMulticastProbes = %q, want = %q", got, test.want) - } - }) - } -} - -func TestNUDConfigurationsMaxUnicastProbes(t *testing.T) { - tests := []struct { - name string - maxUnicastProbes uint32 - want uint32 - }{ - // Invalid cases - { - name: "EqualToZero", - maxUnicastProbes: 0, - want: defaultMaxUnicastProbes, - }, - // Valid cases - { - name: "MoreThanZero", - maxUnicastProbes: 1, - want: 1, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - const nicID = 1 - - c := stack.DefaultNUDConfigurations() - c.MaxUnicastProbes = test.maxUnicastProbes - - e := channel.New(0, 1280, linkAddr1) - e.LinkEPCapabilities |= stack.CapabilityResolutionRequired - - s := stack.New(stack.Options{ - // A neighbor cache is required to store NUDConfigurations. The - // networking stack will only allocate neighbor caches if a protocol - // providing link address resolution is specified (e.g. ARP or IPv6). - NetworkProtocols: []stack.NetworkProtocolFactory{ipv6.NewProtocol}, - NUDConfigs: c, - }) - if err := s.CreateNIC(nicID, e); err != nil { - t.Fatalf("CreateNIC(%d, _) = %s", nicID, err) - } - sc, err := s.NUDConfigurations(nicID, ipv6.ProtocolNumber) - if err != nil { - t.Fatalf("got stack.NUDConfigurations(%d, %d) = %s", nicID, ipv6.ProtocolNumber, err) - } - if got := sc.MaxUnicastProbes; got != test.want { - t.Errorf("got MaxUnicastProbes = %q, want = %q", got, test.want) - } - }) - } -} - -// TestNUDStateReachableTime verifies the correctness of the ReachableTime -// computation. -func TestNUDStateReachableTime(t *testing.T) { - tests := []struct { - name string - baseReachableTime time.Duration - minRandomFactor float32 - maxRandomFactor float32 - want time.Duration - }{ - { - name: "AllZeros", - baseReachableTime: 0, - minRandomFactor: 0, - maxRandomFactor: 0, - want: 0, - }, - { - name: "ZeroMaxRandomFactor", - baseReachableTime: time.Second, - minRandomFactor: 0, - maxRandomFactor: 0, - want: 0, - }, - { - name: "ZeroMinRandomFactor", - baseReachableTime: time.Second, - minRandomFactor: 0, - maxRandomFactor: 1, - want: time.Duration(defaultFakeRandomNum * float32(time.Second)), - }, - { - name: "FractionalRandomFactor", - baseReachableTime: time.Duration(math.MaxInt64), - minRandomFactor: 0.001, - maxRandomFactor: 0.002, - want: time.Duration((0.001 + (0.001 * defaultFakeRandomNum)) * float32(math.MaxInt64)), - }, - { - name: "MinAndMaxRandomFactorsEqual", - baseReachableTime: time.Second, - minRandomFactor: 1, - maxRandomFactor: 1, - want: time.Second, - }, - { - name: "MinAndMaxRandomFactorsDifferent", - baseReachableTime: time.Second, - minRandomFactor: 1, - maxRandomFactor: 2, - want: time.Duration((1.0 + defaultFakeRandomNum) * float32(time.Second)), - }, - { - name: "MaxInt64", - baseReachableTime: time.Duration(math.MaxInt64), - minRandomFactor: 1, - maxRandomFactor: 1, - want: time.Duration(math.MaxInt64), - }, - { - name: "Overflow", - baseReachableTime: time.Duration(math.MaxInt64), - minRandomFactor: 1.5, - maxRandomFactor: 1.5, - want: time.Duration(math.MaxInt64), - }, - { - name: "DoubleOverflow", - baseReachableTime: time.Duration(math.MaxInt64), - minRandomFactor: 2.5, - maxRandomFactor: 2.5, - want: time.Duration(math.MaxInt64), - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - c := stack.NUDConfigurations{ - BaseReachableTime: test.baseReachableTime, - MinRandomFactor: test.minRandomFactor, - MaxRandomFactor: test.maxRandomFactor, - } - // A fake random number generator is used to ensure deterministic - // results. - rng := fakeRand{ - num: defaultFakeRandomNum, - } - var clock faketime.NullClock - s := stack.NewNUDState(c, &clock, rand.New(&rng)) - if got, want := s.ReachableTime(), test.want; got != want { - t.Errorf("got ReachableTime = %q, want = %q", got, want) - } - }) - } -} - -// TestNUDStateRecomputeReachableTime exercises the ReachableTime function -// twice to verify recomputation of reachable time when the min random factor, -// max random factor, or base reachable time changes. -func TestNUDStateRecomputeReachableTime(t *testing.T) { - const defaultBase = time.Second - const defaultMin = 2.0 * defaultMaxRandomFactor - const defaultMax = 3.0 * defaultMaxRandomFactor - - tests := []struct { - name string - baseReachableTime time.Duration - minRandomFactor float32 - maxRandomFactor float32 - want time.Duration - }{ - { - name: "BaseReachableTime", - baseReachableTime: 2 * defaultBase, - minRandomFactor: defaultMin, - maxRandomFactor: defaultMax, - want: time.Duration((defaultMin + (defaultMax-defaultMin)*defaultFakeRandomNum) * float32(2*defaultBase)), - }, - { - name: "MinRandomFactor", - baseReachableTime: defaultBase, - minRandomFactor: defaultMax, - maxRandomFactor: defaultMax, - want: time.Duration(defaultMax * float32(defaultBase)), - }, - { - name: "MaxRandomFactor", - baseReachableTime: defaultBase, - minRandomFactor: defaultMin, - maxRandomFactor: defaultMin, - want: time.Duration(defaultMin * float32(defaultBase)), - }, - { - name: "BothRandomFactor", - baseReachableTime: defaultBase, - minRandomFactor: 2 * defaultMin, - maxRandomFactor: 2 * defaultMax, - want: time.Duration((2*defaultMin + (2*defaultMax-2*defaultMin)*defaultFakeRandomNum) * float32(defaultBase)), - }, - { - name: "BaseReachableTimeAndBothRandomFactors", - baseReachableTime: 2 * defaultBase, - minRandomFactor: 2 * defaultMin, - maxRandomFactor: 2 * defaultMax, - want: time.Duration((2*defaultMin + (2*defaultMax-2*defaultMin)*defaultFakeRandomNum) * float32(2*defaultBase)), - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - c := stack.DefaultNUDConfigurations() - c.BaseReachableTime = defaultBase - c.MinRandomFactor = defaultMin - c.MaxRandomFactor = defaultMax - - // A fake random number generator is used to ensure deterministic - // results. - rng := fakeRand{ - num: defaultFakeRandomNum, - } - var clock faketime.NullClock - s := stack.NewNUDState(c, &clock, rand.New(&rng)) - old := s.ReachableTime() - - if got, want := s.ReachableTime(), old; got != want { - t.Errorf("got ReachableTime = %q, want = %q", got, want) - } - - // Check for recomputation when changing the min random factor, the max - // random factor, the base reachability time, or any permutation of those - // three options. - c.BaseReachableTime = test.baseReachableTime - c.MinRandomFactor = test.minRandomFactor - c.MaxRandomFactor = test.maxRandomFactor - s.SetConfig(c) - - if got, want := s.ReachableTime(), test.want; got != want { - t.Errorf("got ReachableTime = %q, want = %q", got, want) - } - - // Verify that ReachableTime isn't recomputed when none of the - // configuration options change. The random factor is changed so that if - // a recompution were to occur, ReachableTime would change. - rng.num = defaultFakeRandomNum / 2.0 - if got, want := s.ReachableTime(), test.want; got != want { - t.Errorf("got ReachableTime = %q, want = %q", got, want) - } - }) - } -} |