github.com/GoogleCloudPlatform/testgrid@v0.0.174/util/links_test.go (about)

     1  /*
     2  Copyright 2023 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 util
    18  
    19  import (
    20  	"testing"
    21  
    22  	configpb "github.com/GoogleCloudPlatform/testgrid/pb/config"
    23  	"github.com/google/go-cmp/cmp"
    24  	"github.com/google/go-cmp/cmp/cmpopts"
    25  )
    26  
    27  func TestTokens(t *testing.T) {
    28  	cases := []struct {
    29  		name     string
    30  		template *configpb.LinkTemplate
    31  		want     []string
    32  	}{
    33  		{
    34  			name:     "nil",
    35  			template: nil,
    36  			want:     nil,
    37  		},
    38  		{
    39  			name:     "empty",
    40  			template: &configpb.LinkTemplate{},
    41  			want:     nil,
    42  		},
    43  		{
    44  			name: "basically works",
    45  			template: &configpb.LinkTemplate{
    46  				Url: "https://test.com/<workflow-name>/<workflow-id>/<test-id>/<test-name>",
    47  				Options: []*configpb.LinkOptionsTemplate{
    48  					{
    49  						Key:   "prefix",
    50  						Value: "<gcs-prefix>",
    51  					},
    52  					{
    53  						Key:   "build",
    54  						Value: "<build-id>",
    55  					},
    56  					{
    57  						Key:   "prop",
    58  						Value: "<my-prop>",
    59  					},
    60  					{
    61  						Key:   "foo",
    62  						Value: "<custom-0>",
    63  					},
    64  				},
    65  			},
    66  			want: []string{WorkflowName, WorkflowID, TestID, TestName, GcsPrefix, BuildID, "<my-prop>", "<custom-0>"},
    67  		},
    68  		{
    69  			name: "duplicate tokens",
    70  			template: &configpb.LinkTemplate{
    71  				Url: "https://test.com/<workflow-name>/<workflow-id>/<test-id>/<test-id>",
    72  				Options: []*configpb.LinkOptionsTemplate{
    73  					{
    74  						Key:   "workflow",
    75  						Value: "<workflow-name>",
    76  					},
    77  				},
    78  			},
    79  			want: []string{WorkflowName, WorkflowID, TestID},
    80  		},
    81  		{
    82  			name: "encode",
    83  			template: &configpb.LinkTemplate{
    84  				Url: "https://test.com/<encode:<workflow-name>>",
    85  				Options: []*configpb.LinkOptionsTemplate{
    86  					{
    87  						Key:   "workflow-id",
    88  						Value: "<encode:<workflow-id>>",
    89  					},
    90  				},
    91  			},
    92  			want: []string{WorkflowName, WorkflowID},
    93  		},
    94  		{
    95  			name: "invalid",
    96  			template: &configpb.LinkTemplate{
    97  				Url: "http://test.com/<oh-no",
    98  			},
    99  			want: nil,
   100  		},
   101  	}
   102  
   103  	for _, tc := range cases {
   104  		t.Run(tc.name, func(t *testing.T) {
   105  			got := Tokens(tc.template)
   106  			if diff := cmp.Diff(tc.want, got, cmpopts.SortSlices(func(a, b string) bool { return a < b })); diff != "" {
   107  				t.Errorf("Tokens(%v) differed (-want, +got): %s", tc.template, diff)
   108  			}
   109  		})
   110  	}
   111  }
   112  
   113  func TestExpandTemplate(t *testing.T) {
   114  	cases := []struct {
   115  		name       string
   116  		template   *configpb.LinkTemplate
   117  		parameters map[string]string
   118  		err        bool
   119  		want       string
   120  	}{
   121  		{
   122  			name:       "nil",
   123  			template:   nil,
   124  			parameters: nil,
   125  			want:       "",
   126  		},
   127  		{
   128  			name: "nil parameters",
   129  			template: &configpb.LinkTemplate{
   130  				Url: "https://test.com/<workflow-name>/<workflow-id>/<test-id>/<test-name>",
   131  				Options: []*configpb.LinkOptionsTemplate{
   132  					{
   133  						Key:   "prefix",
   134  						Value: "<gcs-prefix>",
   135  					},
   136  					{
   137  						Key:   "build",
   138  						Value: "<build-id>",
   139  					},
   140  					{
   141  						Key:   "prop",
   142  						Value: "<my-prop>",
   143  					},
   144  					{
   145  						Key:   "foo",
   146  						Value: "<custom-0>",
   147  					},
   148  				},
   149  			},
   150  			parameters: nil,
   151  			want:       "https://test.com/%3Cworkflow-name%3E/%3Cworkflow-id%3E/%3Ctest-id%3E/%3Ctest-name%3E?build=%3Cbuild-id%3E&foo=%3Ccustom-0%3E&prefix=%3Cgcs-prefix%3E&prop=%3Cmy-prop%3E",
   152  		},
   153  		{
   154  			name:       "empty",
   155  			template:   &configpb.LinkTemplate{},
   156  			parameters: map[string]string{},
   157  			want:       "",
   158  		},
   159  		{
   160  			name: "basically works",
   161  			template: &configpb.LinkTemplate{
   162  				Url: "https://test.com/<workflow-name>/<workflow-id>/<test-id>/<test-name>",
   163  				Options: []*configpb.LinkOptionsTemplate{
   164  					{
   165  						Key:   "prefix",
   166  						Value: "<gcs-prefix>",
   167  					},
   168  					{
   169  						Key:   "build",
   170  						Value: "<build-id>",
   171  					},
   172  					{
   173  						Key:   "prop",
   174  						Value: "<my-prop>",
   175  					},
   176  					{
   177  						Key:   "foo",
   178  						Value: "<custom-0>",
   179  					},
   180  				},
   181  			},
   182  			parameters: map[string]string{
   183  				WorkflowName: "//my-workflow",
   184  				WorkflowID:   "workflow-id-1",
   185  				TestID:       "test-id-1",
   186  				TestName:     "//path/to:my-test",
   187  				GcsPrefix:    "my-bucket/has/results",
   188  				BuildID:      "build-1",
   189  				"<my-prop>":  "foo",
   190  				"<custom-0>": "bar",
   191  			},
   192  			want: "https://test.com///my-workflow/workflow-id-1/test-id-1///path/to:my-test?build=build-1&foo=bar&prefix=my-bucket%2Fhas%2Fresults&prop=foo",
   193  		},
   194  		{
   195  			name: "invalid url",
   196  			template: &configpb.LinkTemplate{
   197  				Url: "https://test.com%+",
   198  				Options: []*configpb.LinkOptionsTemplate{
   199  					{
   200  						Key:   "prop",
   201  						Value: "%+<my-prop>",
   202  					},
   203  				},
   204  			},
   205  			parameters: map[string]string{
   206  				"<my-prop>": "foo",
   207  			},
   208  			err: true,
   209  		},
   210  		{
   211  			name: "duplicate tokens",
   212  			template: &configpb.LinkTemplate{
   213  				Url: "https://test.com/<test-id>/<test-id>",
   214  				Options: []*configpb.LinkOptionsTemplate{
   215  					{
   216  						Key:   "workflow",
   217  						Value: "<workflow-name>",
   218  					},
   219  					{
   220  						Key:   "workflow-name",
   221  						Value: "<workflow-name>",
   222  					},
   223  				},
   224  			},
   225  			parameters: map[string]string{
   226  				WorkflowName: "//my-workflow",
   227  				WorkflowID:   "workflow-id-1",
   228  				TestID:       "test-id-1",
   229  				TestName:     "//path/to:my-test",
   230  				GcsPrefix:    "my-bucket/has/results",
   231  				BuildID:      "build-1",
   232  				"<my-prop>":  "foo",
   233  			},
   234  			want: "https://test.com/test-id-1/test-id-1?workflow=%2F%2Fmy-workflow&workflow-name=%2F%2Fmy-workflow",
   235  		},
   236  		{
   237  			name: "encode",
   238  			template: &configpb.LinkTemplate{
   239  				Url: "https://test.com/<encode:<workflow-name>>",
   240  				Options: []*configpb.LinkOptionsTemplate{
   241  					{
   242  						Key:   "workflow",
   243  						Value: "<encode:<workflow-name>>",
   244  					},
   245  				},
   246  			},
   247  			parameters: map[string]string{
   248  				WorkflowName: "//my-workfl@w",
   249  			},
   250  			want: "https://test.com/%2F%2Fmy-workfl@w?workflow=%2F%2Fmy-workfl%40w",
   251  		},
   252  		{
   253  			name: "invalid",
   254  			template: &configpb.LinkTemplate{
   255  				Url: "http://test.com/<workflow-name",
   256  			},
   257  			parameters: map[string]string{
   258  				WorkflowName: "//my-workflow",
   259  			},
   260  			want: "http://test.com/%3Cworkflow-name",
   261  		},
   262  	}
   263  
   264  	for _, tc := range cases {
   265  		t.Run(tc.name, func(t *testing.T) {
   266  			got, err := ExpandTemplate(tc.template, tc.parameters)
   267  			if tc.err && err == nil {
   268  				t.Errorf("ExpandTemplate() did not error as expected.")
   269  			} else if !tc.err && err != nil {
   270  				t.Errorf("ExpandTemplate() errored unexpectedly: %v", err)
   271  			}
   272  			if diff := cmp.Diff(tc.want, got); diff != "" {
   273  				t.Errorf("ExpandTemplate() differed (-want, +got): %s", diff)
   274  			}
   275  		})
   276  	}
   277  }
   278  
   279  func TestExpandTemplateString(t *testing.T) {
   280  	cases := []struct {
   281  		name        string
   282  		templateStr string
   283  		parameters  map[string]string
   284  		isQuery     bool
   285  		want        string
   286  	}{
   287  		{
   288  			name:        "empty",
   289  			templateStr: "",
   290  			parameters:  nil,
   291  			want:        "",
   292  		},
   293  		{
   294  			name:        "nil parameters",
   295  			templateStr: "https://test.com/<workflow-name>/<workflow-id>/<test-id>/<test-name>",
   296  			parameters:  nil,
   297  			want:        "https://test.com/<workflow-name>/<workflow-id>/<test-id>/<test-name>",
   298  		},
   299  		{
   300  			name:        "basically works",
   301  			templateStr: "https://test.com/<workflow-name>/<workflow-id>/<test-id>/<test-name>/<my-prop>/<custom-0>",
   302  			parameters: map[string]string{
   303  				WorkflowName: "//my-workflow",
   304  				WorkflowID:   "workflow-id-1",
   305  				TestID:       "test-id-1",
   306  				TestName:     "//path/to:my-test",
   307  				"<my-prop>":  "foo",
   308  				"<custom-0>": "magic",
   309  			},
   310  			want: "https://test.com///my-workflow/workflow-id-1/test-id-1///path/to:my-test/foo/magic",
   311  		},
   312  		{
   313  			name:        "duplicate tokens",
   314  			templateStr: "https://test.com/<test-id>/<test-id>",
   315  			parameters: map[string]string{
   316  				TestID: "test-id-1",
   317  			},
   318  			want: "https://test.com/test-id-1/test-id-1",
   319  		},
   320  		{
   321  			name:        "encode",
   322  			templateStr: "https://test.com/<encode:<workflow-name>>",
   323  			parameters: map[string]string{
   324  				WorkflowName: "//my-workfl@w",
   325  			},
   326  			want: "https://test.com/%2F%2Fmy-workfl@w",
   327  		},
   328  		{
   329  			name:        "encode query",
   330  			templateStr: "<encode:<workflow-name>>",
   331  			parameters: map[string]string{
   332  				WorkflowName: "//my-workfl@w",
   333  			},
   334  			isQuery: true,
   335  			want:    "//my-workfl@w",
   336  		},
   337  		{
   338  			name:        "invalid",
   339  			templateStr: "http://test.com/<workflow-name",
   340  			parameters: map[string]string{
   341  				WorkflowName: "//my-workflow",
   342  			},
   343  			want: "http://test.com/<workflow-name",
   344  		},
   345  	}
   346  
   347  	for _, tc := range cases {
   348  		t.Run(tc.name, func(t *testing.T) {
   349  			got := expandTemplateString(tc.templateStr, tc.parameters, tc.isQuery)
   350  			if diff := cmp.Diff(tc.want, got); diff != "" {
   351  				t.Errorf("expandTemplateString() differed (-want, +got): %s", diff)
   352  			}
   353  		})
   354  	}
   355  }