istio.io/istio@v0.0.0-20240520182934-d79c90f27776/istioctl/pkg/admin/istiodconfig_test.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package admin
    16  
    17  import (
    18  	"net/http"
    19  	"net/http/httptest"
    20  	"net/url"
    21  	"os"
    22  	"reflect"
    23  	"testing"
    24  )
    25  
    26  func Test_newScopeLevelPair(t *testing.T) {
    27  	validationPattern := `^\w+:(debug|error|warn|info|debug)`
    28  	type args struct {
    29  		slp               string
    30  		validationPattern string
    31  	}
    32  	tests := []struct {
    33  		name    string
    34  		args    args
    35  		want    *ScopeLevelPair
    36  		wantErr bool
    37  	}{
    38  		{
    39  			name:    "Fail when logs scope-level pair don't match pattern",
    40  			args:    args{validationPattern: validationPattern, slp: "invalid:pattern"},
    41  			wantErr: true,
    42  		},
    43  	}
    44  	for _, tt := range tests {
    45  		t.Run(tt.name, func(t *testing.T) {
    46  			got, err := newScopeLevelPair(tt.args.slp, tt.args.validationPattern)
    47  			if (err != nil) != tt.wantErr {
    48  				t.Errorf("newScopeLevelPair() error = %v, wantErr %v", err, tt.wantErr)
    49  				return
    50  			}
    51  			if !reflect.DeepEqual(got, tt.want) {
    52  				t.Errorf("newScopeLevelPair() got = %v, want %v", got, tt.want)
    53  			}
    54  		})
    55  	}
    56  }
    57  
    58  func Test_newScopeStackTraceLevelPair(t *testing.T) {
    59  	validationPattern := `^\w+:(debug|error|warn|info|debug)`
    60  	type args struct {
    61  		sslp              string
    62  		validationPattern string
    63  	}
    64  	tests := []struct {
    65  		name    string
    66  		args    args
    67  		want    *scopeStackTraceLevelPair
    68  		wantErr bool
    69  	}{
    70  		{
    71  			name:    "Fail when logs scope-level pair don't match pattern",
    72  			args:    args{validationPattern: validationPattern, sslp: "invalid:pattern"},
    73  			wantErr: true,
    74  		},
    75  	}
    76  	for _, tt := range tests {
    77  		t.Run(tt.name, func(t *testing.T) {
    78  			got, err := newScopeStackTraceLevelPair(tt.args.sslp, tt.args.validationPattern)
    79  			if (err != nil) != tt.wantErr {
    80  				t.Errorf("newScopeStackTraceLevelPair() error = %v, wantErr %v", err, tt.wantErr)
    81  				return
    82  			}
    83  			if !reflect.DeepEqual(got, tt.want) {
    84  				t.Errorf("newScopeStackTraceLevelPair() got = %v, want %v", got, tt.want)
    85  			}
    86  		})
    87  	}
    88  }
    89  
    90  func Test_chooseClientFlag(t *testing.T) {
    91  	url, _ := url.Parse("http://localhost/scopej/resource")
    92  
    93  	ctrzClient := &ControlzClient{
    94  		baseURL:    url,
    95  		httpClient: &http.Client{},
    96  	}
    97  
    98  	type args struct {
    99  		ctrzClient      *ControlzClient
   100  		reset           bool
   101  		outputLogLevel  string
   102  		stackTraceLevel string
   103  		outputFormat    string
   104  	}
   105  	tests := []struct {
   106  		name string
   107  		args args
   108  		want *istiodConfigLog
   109  	}{
   110  		{
   111  			name: "given --reset flag return reset command",
   112  			args: args{
   113  				ctrzClient:      ctrzClient,
   114  				reset:           true,
   115  				outputLogLevel:  "",
   116  				stackTraceLevel: "",
   117  				outputFormat:    "",
   118  			},
   119  			want: &istiodConfigLog{state: &resetState{
   120  				client: ctrzClient,
   121  			}},
   122  		},
   123  		{
   124  			name: "given --level flag return outputLogLevel command",
   125  			args: args{
   126  				ctrzClient:      ctrzClient,
   127  				reset:           false,
   128  				outputLogLevel:  "resource:info",
   129  				stackTraceLevel: "",
   130  				outputFormat:    "",
   131  			},
   132  			want: &istiodConfigLog{state: &logLevelState{
   133  				client:         ctrzClient,
   134  				outputLogLevel: "resource:info",
   135  			}},
   136  		},
   137  		{
   138  			name: "given --stack-trace-level flag return stackTraceLevelState",
   139  			args: args{
   140  				ctrzClient:      ctrzClient,
   141  				reset:           false,
   142  				outputLogLevel:  "",
   143  				stackTraceLevel: "resource:info",
   144  				outputFormat:    "",
   145  			},
   146  			want: &istiodConfigLog{
   147  				state: &stackTraceLevelState{
   148  					client:          ctrzClient,
   149  					stackTraceLevel: "resource:info",
   150  				},
   151  			},
   152  		},
   153  	}
   154  	for _, tt := range tests {
   155  		t.Run(tt.name, func(t *testing.T) {
   156  			if got := chooseClientFlag(tt.args.ctrzClient, tt.args.reset, tt.args.outputLogLevel,
   157  				tt.args.stackTraceLevel, tt.args.outputFormat); !reflect.DeepEqual(got, tt.want) {
   158  				t.Errorf("chooseClientFlag() = %v, want %v", got, tt.want)
   159  			}
   160  		})
   161  	}
   162  }
   163  
   164  func resourceHandler(writer http.ResponseWriter, request *http.Request) {
   165  	const getResponse = `{"name":"resource","description":"Core resource model scope","output_level":"info","stack_trace_level":"none","log_callers":false}`
   166  
   167  	switch request.Method {
   168  	case http.MethodGet:
   169  		_, _ = writer.Write([]byte(getResponse))
   170  	}
   171  }
   172  
   173  func adsHandler(writer http.ResponseWriter, request *http.Request) {
   174  	const getResponse = `{"name":"ads","description":"ads debugging","output_level":"info","stack_trace_level":"none","log_callers":false}`
   175  
   176  	switch request.Method {
   177  	case http.MethodGet:
   178  		_, _ = writer.Write([]byte(getResponse))
   179  	}
   180  }
   181  
   182  func setupHTTPServer() (*httptest.Server, *url.URL) {
   183  	handler := http.NewServeMux()
   184  	handler.HandleFunc("/scopej/ads", adsHandler)
   185  	handler.HandleFunc("/scopej/resource", resourceHandler)
   186  	server := httptest.NewServer(handler)
   187  	url, _ := url.Parse(server.URL)
   188  	return server, url
   189  }
   190  
   191  func Test_flagState_run(t *testing.T) {
   192  	server, url := setupHTTPServer()
   193  	defer server.Close()
   194  
   195  	ctrzClientNoScopejHandler := &ControlzClient{
   196  		baseURL:    url,
   197  		httpClient: &http.Client{},
   198  	}
   199  	tests := []struct {
   200  		name    string
   201  		state   flagState
   202  		want    string
   203  		wantErr bool
   204  	}{
   205  		{
   206  			name:    "resetState.run() should throw an error if the /scopej endpoint is missing",
   207  			state:   &resetState{client: ctrzClientNoScopejHandler},
   208  			wantErr: true,
   209  		},
   210  		{
   211  			name: "logLevelState.run() should throw an error if the /scopej endpoint is missing",
   212  			state: &logLevelState{
   213  				client:         ctrzClientNoScopejHandler,
   214  				outputLogLevel: "test:debug",
   215  			},
   216  			wantErr: true,
   217  		},
   218  		{
   219  			name: "stackTraceLevelState.run() should throw an error if the /scopej endpoint is missing",
   220  			state: &stackTraceLevelState{
   221  				client:          ctrzClientNoScopejHandler,
   222  				stackTraceLevel: "test:debug",
   223  			},
   224  			wantErr: true,
   225  		},
   226  	}
   227  	for _, tt := range tests {
   228  		t.Run(tt.name, func(t *testing.T) {
   229  			err := tt.state.run(os.Stdout)
   230  			if (err != nil) != tt.wantErr {
   231  				t.Errorf("run() error = %v, wantErr %v", err, tt.wantErr)
   232  				return
   233  			}
   234  		})
   235  	}
   236  }