github.com/cilium/cilium@v1.16.2/pkg/health/client/client_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package client
     5  
     6  import (
     7  	"io"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"github.com/cilium/cilium/api/v1/health/models"
    13  )
    14  
    15  func TestConnectivityStatusType(t *testing.T) {
    16  	tests := []struct {
    17  		cst         ConnectivityStatusType
    18  		expectedStr string
    19  	}{
    20  		{
    21  			cst:         ConnStatusReachable,
    22  			expectedStr: "reachable",
    23  		},
    24  		{
    25  			cst:         ConnStatusUnreachable,
    26  			expectedStr: "unreachable",
    27  		},
    28  		{
    29  			cst:         ConnStatusUnknown,
    30  			expectedStr: "unknown",
    31  		},
    32  		{
    33  			cst:         10,
    34  			expectedStr: "unknown",
    35  		},
    36  	}
    37  	for _, tc := range tests {
    38  		t.Run(tc.expectedStr, func(t *testing.T) {
    39  			require.Equal(t, tc.expectedStr, tc.cst.String())
    40  		})
    41  	}
    42  }
    43  
    44  func TestGetConnectivityStatusType(t *testing.T) {
    45  	tests := []struct {
    46  		cs                 *models.ConnectivityStatus
    47  		expectedStatusType ConnectivityStatusType
    48  	}{
    49  		{
    50  			cs:                 &models.ConnectivityStatus{Status: ""},
    51  			expectedStatusType: ConnStatusReachable,
    52  		},
    53  		{
    54  			cs:                 &models.ConnectivityStatus{Status: "failed"},
    55  			expectedStatusType: ConnStatusUnreachable,
    56  		},
    57  		{
    58  			cs:                 nil,
    59  			expectedStatusType: ConnStatusUnknown,
    60  		},
    61  	}
    62  	for _, tc := range tests {
    63  		t.Run(tc.expectedStatusType.String(), func(t *testing.T) {
    64  			require.Equal(t, tc.expectedStatusType, GetConnectivityStatusType(tc.cs))
    65  		})
    66  	}
    67  }
    68  
    69  func TestGetPathConnectivityStatusType(t *testing.T) {
    70  	tests := []struct {
    71  		cp                 *models.PathStatus
    72  		expectedStatusType ConnectivityStatusType
    73  	}{
    74  		{
    75  			cp: &models.PathStatus{
    76  				Icmp: &models.ConnectivityStatus{Status: ""},
    77  				HTTP: &models.ConnectivityStatus{Status: ""},
    78  			},
    79  			expectedStatusType: ConnStatusReachable,
    80  		},
    81  		{
    82  			cp: &models.PathStatus{
    83  				Icmp: &models.ConnectivityStatus{Status: "failed"},
    84  				HTTP: &models.ConnectivityStatus{Status: "failed"},
    85  			},
    86  			expectedStatusType: ConnStatusUnreachable,
    87  		},
    88  		{
    89  			cp: &models.PathStatus{
    90  				Icmp: &models.ConnectivityStatus{Status: ""},
    91  				HTTP: &models.ConnectivityStatus{Status: "failed"},
    92  			},
    93  			expectedStatusType: ConnStatusUnreachable,
    94  		},
    95  		{
    96  			cp: &models.PathStatus{
    97  				Icmp: &models.ConnectivityStatus{Status: "failed"},
    98  				HTTP: &models.ConnectivityStatus{Status: ""},
    99  			},
   100  			expectedStatusType: ConnStatusUnreachable,
   101  		},
   102  		{
   103  			cp: &models.PathStatus{
   104  				Icmp: &models.ConnectivityStatus{Status: "failed"},
   105  				HTTP: nil,
   106  			},
   107  			expectedStatusType: ConnStatusUnreachable,
   108  		},
   109  		{
   110  			cp: &models.PathStatus{
   111  				Icmp: nil,
   112  				HTTP: &models.ConnectivityStatus{Status: "failed"},
   113  			},
   114  			expectedStatusType: ConnStatusUnreachable,
   115  		},
   116  		{
   117  			cp: &models.PathStatus{
   118  				Icmp: nil,
   119  				HTTP: nil,
   120  			},
   121  			expectedStatusType: ConnStatusUnknown,
   122  		},
   123  		{
   124  			cp: &models.PathStatus{
   125  				Icmp: &models.ConnectivityStatus{Status: ""},
   126  				HTTP: nil,
   127  			},
   128  			expectedStatusType: ConnStatusUnknown,
   129  		},
   130  		{
   131  			cp: &models.PathStatus{
   132  				Icmp: nil,
   133  				HTTP: &models.ConnectivityStatus{Status: ""},
   134  			},
   135  			expectedStatusType: ConnStatusUnknown,
   136  		},
   137  	}
   138  	for _, tc := range tests {
   139  		t.Run(tc.expectedStatusType.String(), func(t *testing.T) {
   140  			require.Equal(t, tc.expectedStatusType, GetPathConnectivityStatusType(tc.cp))
   141  		})
   142  	}
   143  }
   144  
   145  func TestFormatNodeStatus(t *testing.T) {
   146  	// This test generates permutations of models.NodeStatus and sees whether
   147  	// the calls to formatNodeStatus panic; the result of this test being
   148  	// successful is whether the test does not panic.
   149  
   150  	// not testing output, just that permutations of NodeStatus don't cause
   151  	// panics.
   152  	w := io.Discard
   153  
   154  	connectivityStatusGood := &models.ConnectivityStatus{
   155  		Latency: 1,
   156  		Status:  "",
   157  	}
   158  	connectivityStatusBad := &models.ConnectivityStatus{
   159  		Latency: 1,
   160  		Status:  "bad status",
   161  	}
   162  	possibleConnectivityStatus := []*models.ConnectivityStatus{
   163  		connectivityStatusBad,
   164  		connectivityStatusGood,
   165  	}
   166  	possibleIPs := []string{"192.168.1.1", ""}
   167  
   168  	possibleNames := []string{"node1", ""}
   169  
   170  	possiblePathStatuses := []*models.PathStatus{}
   171  
   172  	for _, connectivityStatusHTTP := range possibleConnectivityStatus {
   173  		for _, connectivityStatusICMP := range possibleConnectivityStatus {
   174  			for _, possibleIP := range possibleIPs {
   175  				pathStatus := &models.PathStatus{
   176  					HTTP: connectivityStatusHTTP,
   177  					Icmp: connectivityStatusICMP,
   178  					IP:   possibleIP,
   179  				}
   180  				possiblePathStatuses = append(possiblePathStatuses, pathStatus)
   181  			}
   182  		}
   183  	}
   184  
   185  	possibleSecondaryAddresses := make([]*models.PathStatus, 0, len(possiblePathStatuses)+1)
   186  	possibleSecondaryAddresses = append(possibleSecondaryAddresses, nil)
   187  	possibleSecondaryAddresses = append(possibleSecondaryAddresses, possiblePathStatuses...)
   188  
   189  	// Assemble possible host statuses.
   190  	possibleHostStatuses := []*models.HostStatus{
   191  		nil,
   192  	}
   193  
   194  	for _, possiblePrimaryAddress := range possiblePathStatuses {
   195  		hostStatus := &models.HostStatus{
   196  			PrimaryAddress:     possiblePrimaryAddress,
   197  			SecondaryAddresses: possibleSecondaryAddresses,
   198  		}
   199  		possibleHostStatuses = append(possibleHostStatuses, hostStatus)
   200  	}
   201  
   202  	// Assemble possible health-endpoint statuses.
   203  	possibleEndpointStatuses := []*models.EndpointStatus{
   204  		nil,
   205  	}
   206  	for _, possiblePrimaryAddress := range possiblePathStatuses {
   207  		hostStatus := &models.EndpointStatus{
   208  			PrimaryAddress:     possiblePrimaryAddress,
   209  			SecondaryAddresses: possibleSecondaryAddresses,
   210  		}
   211  		possibleEndpointStatuses = append(possibleEndpointStatuses, hostStatus)
   212  	}
   213  
   214  	printAllOptions := []bool{true, false}
   215  	succinctOptions := []bool{true, false}
   216  	verboseOptions := []bool{true, false}
   217  	localhostOptions := []bool{true, false}
   218  
   219  	for _, possibleEndpointStatus := range possibleEndpointStatuses {
   220  		for _, hostStatus := range possibleHostStatuses {
   221  			for _, name := range possibleNames {
   222  				ns := &models.NodeStatus{
   223  					HealthEndpoint: possibleEndpointStatus,
   224  					Host:           hostStatus,
   225  					Name:           name,
   226  				}
   227  				for _, printAllOpt := range printAllOptions {
   228  					for _, succintOpt := range succinctOptions {
   229  						for _, verboseOpt := range verboseOptions {
   230  							for _, localhostOpt := range localhostOptions {
   231  								formatNodeStatus(w, ns, printAllOpt, succintOpt, verboseOpt, localhostOpt)
   232  							}
   233  						}
   234  					}
   235  				}
   236  			}
   237  		}
   238  	}
   239  }
   240  
   241  func TestGetHostPrimaryAddress(t *testing.T) {
   242  	nilHostNS := &models.NodeStatus{
   243  		Host: nil,
   244  	}
   245  
   246  	pathStatus := GetHostPrimaryAddress(nilHostNS)
   247  	require.Nil(t, pathStatus)
   248  
   249  	nilPrimaryAddressNS := &models.NodeStatus{
   250  		Host: &models.HostStatus{
   251  			PrimaryAddress: nil,
   252  		},
   253  	}
   254  
   255  	pathStatus = GetHostPrimaryAddress(nilPrimaryAddressNS)
   256  	require.Nil(t, pathStatus)
   257  
   258  	primaryAddressNS := &models.NodeStatus{
   259  		Host: &models.HostStatus{
   260  			PrimaryAddress: &models.PathStatus{},
   261  		},
   262  	}
   263  
   264  	pathStatus = GetHostPrimaryAddress(primaryAddressNS)
   265  	require.NotNil(t, pathStatus)
   266  }
   267  
   268  func TestGetPrimaryAddressIP(t *testing.T) {
   269  	nilHostNS := &models.NodeStatus{
   270  		Host: nil,
   271  	}
   272  
   273  	pathStatus := getPrimaryAddressIP(nilHostNS)
   274  	require.Equal(t, ipUnavailable, pathStatus)
   275  
   276  	nilPrimaryAddressNS := &models.NodeStatus{
   277  		Host: &models.HostStatus{
   278  			PrimaryAddress: nil,
   279  		},
   280  	}
   281  
   282  	pathStatus = getPrimaryAddressIP(nilPrimaryAddressNS)
   283  	require.Equal(t, ipUnavailable, pathStatus)
   284  
   285  	primaryAddressNS := &models.NodeStatus{
   286  		Host: &models.HostStatus{
   287  			PrimaryAddress: &models.PathStatus{},
   288  		},
   289  	}
   290  
   291  	pathStatus = getPrimaryAddressIP(primaryAddressNS)
   292  	require.Empty(t, pathStatus)
   293  }
   294  
   295  func TestGetAllEndpointAddresses(t *testing.T) {
   296  	var (
   297  		primary    = models.PathStatus{IP: "1.1.1.1"}
   298  		secondary1 = models.PathStatus{IP: "2.2.2.2"}
   299  		secondary2 = models.PathStatus{IP: "3.3.3.3"}
   300  	)
   301  
   302  	tests := []struct {
   303  		node     *models.NodeStatus
   304  		expected []*models.PathStatus
   305  	}{
   306  		{
   307  			node:     &models.NodeStatus{},
   308  			expected: nil,
   309  		},
   310  		{
   311  			node: &models.NodeStatus{
   312  				HealthEndpoint: &models.EndpointStatus{
   313  					PrimaryAddress: &primary,
   314  				}},
   315  			expected: []*models.PathStatus{&primary},
   316  		},
   317  		{
   318  			node: &models.NodeStatus{
   319  				HealthEndpoint: &models.EndpointStatus{
   320  					PrimaryAddress:     &primary,
   321  					SecondaryAddresses: []*models.PathStatus{&secondary1, &secondary2},
   322  				}},
   323  			expected: []*models.PathStatus{&primary, &secondary1, &secondary2},
   324  		},
   325  	}
   326  	for _, tc := range tests {
   327  		require.Equal(t, tc.expected, GetAllEndpointAddresses(tc.node))
   328  	}
   329  }