github.com/google/osv-scalibr@v0.4.1/detector/weakcredentials/codeserver/codeserver_test.go (about)

     1  // Copyright 2025 Google LLC
     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 codeserver
    16  
    17  import (
    18  	"fmt"
    19  	"io"
    20  	"net/http"
    21  	"net/http/httptest"
    22  	"os"
    23  	"testing"
    24  	"time"
    25  )
    26  
    27  func TestScan(t *testing.T) {
    28  	tests := []struct {
    29  		name      string
    30  		handler   http.HandlerFunc
    31  		wantVulns bool
    32  	}{
    33  
    34  		{
    35  			name:      "auth_disabled_returns_vuln",
    36  			handler:   validHandler(t, false),
    37  			wantVulns: true,
    38  		},
    39  		{
    40  			name:      "auth_enabled_returns_nothing",
    41  			handler:   validHandler(t, true),
    42  			wantVulns: false,
    43  		},
    44  		{
    45  			name: "login_returns_non_200_code_returns_nothing",
    46  			handler: func(w http.ResponseWriter, r *http.Request) {
    47  				w.WriteHeader(http.StatusForbidden)
    48  			},
    49  			wantVulns: false,
    50  		},
    51  	}
    52  
    53  	for _, tc := range tests {
    54  		t.Run(tc.name, func(t *testing.T) {
    55  			srv := httptest.NewServer(tc.handler)
    56  			defer srv.Close()
    57  
    58  			cfg := DefaultConfig()
    59  			cfg.Remote = srv.URL
    60  
    61  			d := New(cfg)
    62  			invs, _ := d.Scan(t.Context(), nil, nil)
    63  
    64  			gotVulns := len(invs.GenericFindings) > 0
    65  			if gotVulns != tc.wantVulns {
    66  				t.Errorf("Scan() returned unexpected vulnerabilities, got findings: %v, want findings: %v", gotVulns, tc.wantVulns)
    67  			}
    68  		})
    69  	}
    70  }
    71  
    72  func TestScanWithTimeouts(t *testing.T) {
    73  	tests := []struct {
    74  		name          string
    75  		handler       http.HandlerFunc
    76  		expectFails   bool
    77  		clientTimeout time.Duration
    78  		maxDuration   time.Duration
    79  	}{
    80  		{
    81  			name: "auth_staled_timeouts",
    82  			handler: func(w http.ResponseWriter, r *http.Request) {
    83  				time.Sleep(2 * time.Second)
    84  			},
    85  			expectFails:   false,
    86  			clientTimeout: 100 * time.Millisecond,
    87  			maxDuration:   180 * time.Millisecond,
    88  		},
    89  	}
    90  
    91  	for _, tc := range tests {
    92  		t.Run(tc.name, func(t *testing.T) {
    93  			srv := httptest.NewServer(tc.handler)
    94  			defer srv.Close()
    95  
    96  			cfg := DefaultConfig()
    97  			cfg.Remote = srv.URL
    98  			cfg.ClientTimeout = tc.clientTimeout
    99  
   100  			d := New(cfg)
   101  			start := time.Now()
   102  			invs, err := d.Scan(t.Context(), nil, nil)
   103  			end := time.Now()
   104  
   105  			if tc.expectFails != (err != nil) {
   106  				t.Errorf("Scan() unexpected error, got: %v", err)
   107  			}
   108  
   109  			if len(invs.GenericFindings) != 0 {
   110  				t.Errorf("Scan() returned unexpected findings, got: %v, want nothing", invs)
   111  			}
   112  
   113  			if end.Sub(start) > tc.maxDuration {
   114  				t.Errorf("Scan() took too long: %v", end.Sub(start))
   115  			}
   116  		})
   117  	}
   118  }
   119  
   120  func TestDefaultConfig(t *testing.T) {
   121  	tests := []struct {
   122  		name    string
   123  		goos    string
   124  		wantURL string
   125  	}{
   126  		{
   127  			name:    "darwin",
   128  			goos:    "darwin",
   129  			wantURL: "http://localhost:49363",
   130  		},
   131  		{
   132  			name:    "linux",
   133  			goos:    "linux",
   134  			wantURL: "http://127.0.0.2:49363",
   135  		},
   136  		{
   137  			name:    "windows",
   138  			goos:    "windows",
   139  			wantURL: "http://127.0.0.2:49363",
   140  		},
   141  	}
   142  
   143  	for _, tc := range tests {
   144  		t.Run(tc.name, func(t *testing.T) {
   145  			cfg := defaultConfigWithOS(tc.goos)
   146  			if cfg.Remote != tc.wantURL {
   147  				t.Errorf("defaultConfigWithOS(%q).Remote = %q, want %q", tc.goos, cfg.Remote, tc.wantURL)
   148  			}
   149  		})
   150  	}
   151  }
   152  
   153  // validHandler returns a valid handler that will emulate the Code-Server instance. Does not emulate
   154  // the redirection.
   155  func validHandler(t *testing.T, authEnabled bool) http.HandlerFunc {
   156  	t.Helper()
   157  
   158  	return func(w http.ResponseWriter, r *http.Request) {
   159  		if authEnabled {
   160  			fmt.Fprintln(w, loadTestFile(t, "testdata/auth_enabled.html"))
   161  			return
   162  		}
   163  		fmt.Fprintln(w, loadTestFile(t, "testdata/auth_disabled.html"))
   164  	}
   165  }
   166  
   167  func loadTestFile(t *testing.T, filename string) string {
   168  	t.Helper()
   169  	f, err := os.Open(filename)
   170  	if err != nil {
   171  		t.Fatalf("failed to open %s: %v", filename, err)
   172  	}
   173  
   174  	content, err := io.ReadAll(f)
   175  	if err != nil {
   176  		t.Fatalf("failed to read %s: %v", filename, err)
   177  	}
   178  
   179  	return string(content)
   180  }