github.com/GoogleCloudPlatform/testgrid@v0.0.174/pkg/api/v1/config_test.go (about)

     1  /*
     2  Copyright 2022 The TestGrid Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package v1
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	apipb "github.com/GoogleCloudPlatform/testgrid/pb/api/v1"
    24  	configpb "github.com/GoogleCloudPlatform/testgrid/pb/config"
    25  	"github.com/GoogleCloudPlatform/testgrid/util/gcs"
    26  	"github.com/google/go-cmp/cmp"
    27  	"google.golang.org/protobuf/testing/protocmp"
    28  )
    29  
    30  func getPathOrDie(t *testing.T, s string) *gcs.Path {
    31  	t.Helper()
    32  	path, err := gcs.NewPath(s)
    33  	if err != nil {
    34  		t.Fatalf("Couldn't make path %s: %v", s, err)
    35  	}
    36  	return path
    37  }
    38  
    39  func Test_GetDashboardGroup(t *testing.T) {
    40  	tests := []struct {
    41  		name        string
    42  		config      map[string]*configpb.Configuration
    43  		req         *apipb.GetDashboardGroupRequest
    44  		expected    *apipb.GetDashboardGroupResponse
    45  		expectError bool
    46  	}{
    47  		{
    48  			name: "Returns an error when there's no resource",
    49  			config: map[string]*configpb.Configuration{
    50  				"gs://default/config": {},
    51  			},
    52  			req: &apipb.GetDashboardGroupRequest{
    53  				DashboardGroup: "",
    54  			},
    55  			expectError: true,
    56  		},
    57  		{
    58  			name: "Returns empty response from an empty Dashboard Group",
    59  			config: map[string]*configpb.Configuration{
    60  				"gs://default/config": {
    61  					DashboardGroups: []*configpb.DashboardGroup{
    62  						{
    63  							Name: "Group1",
    64  						},
    65  					},
    66  				},
    67  			},
    68  			req: &apipb.GetDashboardGroupRequest{
    69  				DashboardGroup: "group1",
    70  			},
    71  			expected: &apipb.GetDashboardGroupResponse{},
    72  		},
    73  		{
    74  			name: "Returns dashboards from group",
    75  			config: map[string]*configpb.Configuration{
    76  				"gs://default/config": {
    77  					DashboardGroups: []*configpb.DashboardGroup{
    78  						{
    79  							Name:           "stooges",
    80  							DashboardNames: []string{"Larry", "Curly", "Moe"},
    81  						},
    82  					},
    83  				},
    84  			},
    85  			req: &apipb.GetDashboardGroupRequest{
    86  				DashboardGroup: "stooges",
    87  			},
    88  			expected: &apipb.GetDashboardGroupResponse{
    89  				Dashboards: []*apipb.Resource{
    90  					{Name: "Curly", Link: "/dashboards/curly"},
    91  					{Name: "Larry", Link: "/dashboards/larry"},
    92  					{Name: "Moe", Link: "/dashboards/moe"},
    93  				},
    94  			},
    95  		},
    96  		{
    97  			name: "Reads specified configs",
    98  			config: map[string]*configpb.Configuration{
    99  				"gs://default/config": {
   100  					DashboardGroups: []*configpb.DashboardGroup{
   101  						{
   102  							Name:           "wrong-group",
   103  							DashboardNames: []string{"no"},
   104  						},
   105  					},
   106  				},
   107  				"gs://example/config": {
   108  					DashboardGroups: []*configpb.DashboardGroup{
   109  						{
   110  							Name:           "right-group",
   111  							DashboardNames: []string{"yes"},
   112  						},
   113  					},
   114  				},
   115  			},
   116  			req: &apipb.GetDashboardGroupRequest{
   117  				DashboardGroup: "right-group",
   118  				Scope:          "gs://example",
   119  			},
   120  			expected: &apipb.GetDashboardGroupResponse{
   121  				Dashboards: []*apipb.Resource{
   122  					{Name: "yes", Link: "/dashboards/yes?scope=gs://example"},
   123  				},
   124  			},
   125  		},
   126  		{
   127  			name: "Specified configs never reads default config",
   128  			config: map[string]*configpb.Configuration{
   129  				"gs://default/config": {
   130  					DashboardGroups: []*configpb.DashboardGroup{
   131  						{
   132  							Name:           "wrong-group",
   133  							DashboardNames: []string{"no"},
   134  						},
   135  					},
   136  				},
   137  				"gs://example/config": {
   138  					DashboardGroups: []*configpb.DashboardGroup{
   139  						{
   140  							Name:           "right-group",
   141  							DashboardNames: []string{"yes"},
   142  						},
   143  					},
   144  				},
   145  			},
   146  			req: &apipb.GetDashboardGroupRequest{
   147  				DashboardGroup: "wrong-group",
   148  				Scope:          "gs://example",
   149  			},
   150  			expectError: true,
   151  		},
   152  		{
   153  			name: "Server error with unreadable config",
   154  			req: &apipb.GetDashboardGroupRequest{
   155  				DashboardGroup: "group",
   156  				Scope:          "garbage",
   157  			},
   158  			expectError: true,
   159  		},
   160  	}
   161  	for _, tc := range tests {
   162  		t.Run(tc.name, func(t *testing.T) {
   163  			server := setupTestServer(t, tc.config, nil, nil)
   164  			actual, err := server.GetDashboardGroup(context.Background(), tc.req)
   165  			if !tc.expectError && err != nil {
   166  				t.Errorf("Unexpected error: %v", err)
   167  			}
   168  			if tc.expectError && err == nil {
   169  				t.Errorf("Expected error, but got none")
   170  			}
   171  			if diff := cmp.Diff(actual, tc.expected, protocmp.Transform()); diff != "" {
   172  				t.Errorf("(-got, +want): %s", diff)
   173  			}
   174  		})
   175  	}
   176  }
   177  
   178  func Test_GetDashboard(t *testing.T) {
   179  	tests := []struct {
   180  		name        string
   181  		config      map[string]*configpb.Configuration
   182  		req         *apipb.GetDashboardRequest
   183  		expected    *apipb.GetDashboardResponse
   184  		expectError bool
   185  	}{
   186  		{
   187  			name: "Returns an error when there's no resource",
   188  			config: map[string]*configpb.Configuration{
   189  				"gs://default/config": {},
   190  			},
   191  			req: &apipb.GetDashboardRequest{
   192  				Dashboard: "",
   193  			},
   194  			expectError: true,
   195  		},
   196  		{
   197  			name: "Returns empty JSON from an empty Dashboard",
   198  			config: map[string]*configpb.Configuration{
   199  				"gs://default/config": {
   200  					Dashboards: []*configpb.Dashboard{
   201  						{
   202  							Name: "Dashboard1",
   203  						},
   204  					},
   205  				},
   206  			},
   207  			req: &apipb.GetDashboardRequest{
   208  				Dashboard: "Dashboard1",
   209  			},
   210  			expected: &apipb.GetDashboardResponse{},
   211  		},
   212  		{
   213  			name: "Returns dashboard info from dashboard",
   214  			config: map[string]*configpb.Configuration{
   215  				"gs://default/config": {
   216  					Dashboards: []*configpb.Dashboard{
   217  						{
   218  							Name:                "Dashboard1",
   219  							DefaultTab:          "defaultTab",
   220  							HighlightToday:      true,
   221  							DownplayFailingTabs: true,
   222  							Notifications: []*configpb.Notification{
   223  								{
   224  									Summary:     "Notification summary",
   225  									ContextLink: "Notification context link",
   226  								},
   227  							},
   228  						},
   229  					},
   230  				},
   231  			},
   232  			req: &apipb.GetDashboardRequest{
   233  				Dashboard: "Dashboard-1",
   234  			},
   235  			expected: &apipb.GetDashboardResponse{
   236  				Notifications: []*configpb.Notification{
   237  					{Summary: "Notification summary", ContextLink: "Notification context link"},
   238  				},
   239  				DefaultTab:          "defaultTab",
   240  				HighlightToday:      true,
   241  				SuppressFailingTabs: true,
   242  			},
   243  		},
   244  		{
   245  			name: "Reads specified configs",
   246  			config: map[string]*configpb.Configuration{
   247  				"gs://default/config": {
   248  					Dashboards: []*configpb.Dashboard{
   249  						{
   250  							Name:       "wrong-dashboard",
   251  							DefaultTab: "wrong-dashboard defaultTab",
   252  						},
   253  					},
   254  				},
   255  				"gs://example/config": {
   256  					Dashboards: []*configpb.Dashboard{
   257  						{
   258  							Name:           "correct-dashboard",
   259  							DefaultTab:     "correct-dashboard defaultTab",
   260  							HighlightToday: true,
   261  						},
   262  					},
   263  				},
   264  			},
   265  			req: &apipb.GetDashboardRequest{
   266  				Dashboard: "correct-dashboard",
   267  				Scope:     "gs://example",
   268  			},
   269  			expected: &apipb.GetDashboardResponse{
   270  				HighlightToday: true,
   271  				DefaultTab:     "correct-dashboard defaultTab",
   272  			},
   273  		},
   274  		{
   275  			name: "Specified configs never reads default config",
   276  			config: map[string]*configpb.Configuration{
   277  				"gs://default/config": {
   278  					Dashboards: []*configpb.Dashboard{
   279  						{
   280  							Name:       "wrong-dashboard",
   281  							DefaultTab: "wrong-dashboard defaultTab",
   282  						},
   283  					},
   284  				},
   285  				"gs://example/config": {
   286  					Dashboards: []*configpb.Dashboard{
   287  						{
   288  							Name:       "correct-dashboard",
   289  							DefaultTab: "correct-dashboard defaultTab",
   290  						},
   291  					},
   292  				},
   293  			},
   294  			req: &apipb.GetDashboardRequest{
   295  				Dashboard: "wrong-dashboard",
   296  				Scope:     "gs://example",
   297  			},
   298  			expectError: true,
   299  		},
   300  		{
   301  			name: "Server error with unreadable config",
   302  			req: &apipb.GetDashboardRequest{
   303  				Dashboard: "who",
   304  			},
   305  			expectError: true,
   306  		},
   307  	}
   308  
   309  	for _, tc := range tests {
   310  		t.Run(tc.name, func(t *testing.T) {
   311  			server := setupTestServer(t, tc.config, nil, nil)
   312  			actual, err := server.GetDashboard(context.Background(), tc.req)
   313  			if !tc.expectError && err != nil {
   314  				t.Errorf("Unexpected error: %v", err)
   315  			}
   316  			if tc.expectError && err == nil {
   317  				t.Errorf("Expected error, but got none")
   318  			}
   319  			if diff := cmp.Diff(actual, tc.expected, protocmp.Transform()); diff != "" {
   320  				t.Errorf("(-got, +want): %s", diff)
   321  			}
   322  		})
   323  	}
   324  }
   325  
   326  func Test_ListDashboardTabs(t *testing.T) {
   327  	tests := []struct {
   328  		name        string
   329  		config      map[string]*configpb.Configuration
   330  		req         *apipb.ListDashboardTabsRequest
   331  		expected    *apipb.ListDashboardTabsResponse
   332  		expectError bool
   333  	}{
   334  		{
   335  			name: "Returns an error when there's no resource",
   336  			config: map[string]*configpb.Configuration{
   337  				"gs://default/config": {},
   338  			},
   339  			req: &apipb.ListDashboardTabsRequest{
   340  				Dashboard: "",
   341  			},
   342  			expectError: true,
   343  		},
   344  		{
   345  			name: "Returns empty JSON from an empty Dashboard",
   346  			config: map[string]*configpb.Configuration{
   347  				"gs://default/config": {
   348  					Dashboards: []*configpb.Dashboard{
   349  						{
   350  							Name:         "Dashboard1",
   351  							DashboardTab: []*configpb.DashboardTab{},
   352  						},
   353  					},
   354  				},
   355  			},
   356  			req: &apipb.ListDashboardTabsRequest{
   357  				Dashboard: "Dashboard1",
   358  			},
   359  			expected: &apipb.ListDashboardTabsResponse{},
   360  		},
   361  		{
   362  			name: "Returns tabs list from a Dashboard",
   363  			config: map[string]*configpb.Configuration{
   364  				"gs://default/config": {
   365  					Dashboards: []*configpb.Dashboard{
   366  						{
   367  							Name: "Dashboard1",
   368  							DashboardTab: []*configpb.DashboardTab{
   369  								{
   370  									Name: "tab 1",
   371  								},
   372  								{
   373  									Name: "tab 2",
   374  								},
   375  							},
   376  						},
   377  					},
   378  				},
   379  			},
   380  			req: &apipb.ListDashboardTabsRequest{
   381  				Dashboard: "Dashboard1",
   382  			},
   383  			expected: &apipb.ListDashboardTabsResponse{
   384  				DashboardTabs: []*apipb.Resource{
   385  					{Name: "tab 1", Link: "/dashboards/dashboard1/tabs/tab1"},
   386  					{Name: "tab 2", Link: "/dashboards/dashboard1/tabs/tab2"},
   387  				},
   388  			},
   389  		},
   390  		{
   391  			name: "Reads specified configs",
   392  			config: map[string]*configpb.Configuration{
   393  				"gs://default/config": {
   394  					Dashboards: []*configpb.Dashboard{
   395  						{
   396  							Name: "wrong-dashboard",
   397  							DashboardTab: []*configpb.DashboardTab{
   398  								{
   399  									Name: "wrong-dashboard tab 1",
   400  								},
   401  							},
   402  						},
   403  					},
   404  				},
   405  				"gs://example/config": {
   406  					Dashboards: []*configpb.Dashboard{
   407  						{
   408  							Name: "correct-dashboard",
   409  							DashboardTab: []*configpb.DashboardTab{
   410  								{
   411  									Name: "correct-dashboard tab 1",
   412  								},
   413  							},
   414  						},
   415  					},
   416  				},
   417  			},
   418  			req: &apipb.ListDashboardTabsRequest{
   419  				Dashboard: "correct-dashboard",
   420  				Scope:     "gs://example",
   421  			},
   422  			expected: &apipb.ListDashboardTabsResponse{
   423  				DashboardTabs: []*apipb.Resource{
   424  					{Name: "correct-dashboard tab 1", Link: "/dashboards/correctdashboard/tabs/correctdashboardtab1?scope=gs://example"},
   425  				},
   426  			},
   427  		},
   428  		{
   429  			name: "Specified configs never reads default config",
   430  			config: map[string]*configpb.Configuration{
   431  				"gs://default/config": {
   432  					Dashboards: []*configpb.Dashboard{
   433  						{
   434  							Name: "wrong-dashboard",
   435  							DashboardTab: []*configpb.DashboardTab{
   436  								{
   437  									Name: "wrong-dashboard tab 1",
   438  								},
   439  							},
   440  						},
   441  					},
   442  				},
   443  				"gs://example/config": {
   444  					Dashboards: []*configpb.Dashboard{
   445  						{
   446  							Name: "correct-dashboard",
   447  							DashboardTab: []*configpb.DashboardTab{
   448  								{
   449  									Name: "correct-dashboard tab 1",
   450  								},
   451  							},
   452  						},
   453  					},
   454  				},
   455  			},
   456  			req: &apipb.ListDashboardTabsRequest{
   457  				Dashboard: "wrong-dashboard",
   458  				Scope:     "gs://example",
   459  			},
   460  			expectError: true,
   461  		},
   462  		{
   463  			name: "Server error with unreadable config",
   464  			req: &apipb.ListDashboardTabsRequest{
   465  				Dashboard: "dashboard1",
   466  				Scope:     "gibberish",
   467  			},
   468  			expectError: true,
   469  		},
   470  	}
   471  
   472  	for _, tc := range tests {
   473  		t.Run(tc.name, func(t *testing.T) {
   474  			server := setupTestServer(t, tc.config, nil, nil)
   475  			actual, err := server.ListDashboardTabs(context.Background(), tc.req)
   476  			if !tc.expectError && err != nil {
   477  				t.Errorf("Unexpected error: %v", err)
   478  			}
   479  			if tc.expectError && err == nil {
   480  				t.Errorf("Expected error, but got none")
   481  			}
   482  			if diff := cmp.Diff(actual, tc.expected, protocmp.Transform()); diff != "" {
   483  				t.Errorf("(-got, +want): %s", diff)
   484  			}
   485  		})
   486  	}
   487  }
   488  
   489  // These methods are currently covered in HTTP tests only:
   490  // ListDashboardGroup
   491  // ListDashboard