go.fuchsia.dev/infra@v0.0.0-20240507153436-9b593402251b/cmd/roller-configurator/resolve_test.go (about)

     1  // Copyright 2023 The Fuchsia Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style license that can be
     3  // found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"context"
     9  	"encoding/json"
    10  	"strings"
    11  	"testing"
    12  
    13  	"github.com/google/go-cmp/cmp"
    14  	"go.fuchsia.dev/infra/cmd/roller-configurator/proto"
    15  	"google.golang.org/protobuf/encoding/prototext"
    16  )
    17  
    18  var testFiles = map[string]string{
    19  	".gitmodules": `
    20  		[submodule "path/to/submodule"]
    21  			url = "https://example.com/lib"
    22  	`,
    23  	"path/to/jiri_manifest": `
    24  		<?xml version="1.0" encoding="UTF-8"?>
    25  		<manifest>
    26  			<projects>
    27  				<project name="foo-project"
    28  						 remote="https://example.com/jiri-project"
    29  						 anotherfield="bar"/>
    30  			</projects>
    31  			<packages>
    32  				<package name="foo/package1/${platform}"
    33  						 anotherfield="baz"/>
    34  				<package name="foo/package2/${platform}"
    35  						 anotherfield="baz"/>
    36  			</packages>
    37  		</manifest>
    38  	`,
    39  }
    40  
    41  func TestResolve(t *testing.T) {
    42  	t.Parallel()
    43  
    44  	testCases := []struct {
    45  		name  string
    46  		input string
    47  		want  string
    48  	}{
    49  		{
    50  			name:  "empty",
    51  			input: `rollers: []`,
    52  			want:  `[]`,
    53  		},
    54  		{
    55  			name: "submodule roller",
    56  			input: `rollers: [
    57  				{
    58  					submodule: {
    59  						path: "path/to/submodule"
    60  					}
    61  					schedule: "* * * * *"
    62  				}
    63  			]`,
    64  			want: `[
    65  				{
    66  					"type": "submodule",
    67  					"path": "path/to/submodule",
    68  					"remote": "https://example.com/lib",
    69  					"schedule": "* * * * *",
    70  					"force_submit": false,
    71  					"notify_emails": [],
    72  					"owner_email": ""
    73  				}
    74  			]`,
    75  		},
    76  		{
    77  			name: "jiri project roller",
    78  			input: `rollers: [
    79  				{
    80  					jiri_project: {
    81  						manifest: "path/to/jiri_manifest"
    82  						project: "foo-project"
    83  					}
    84  				}
    85  			]
    86  			default_checkout_jiri_manifest: "manifest"
    87  			`,
    88  			want: `[
    89  				{
    90  					"type": "jiri_project",
    91  					"manifest": "path/to/jiri_manifest",
    92  					"project": "foo-project",
    93  					"remote": "https://example.com/jiri-project",
    94  					"remote_branch": "",
    95  					"checkout_manifest": "manifest",
    96  					"schedule": "",
    97  					"force_submit": false,
    98  					"notify_emails": [],
    99  					"owner_email": ""
   100  				}
   101  			]`,
   102  		},
   103  		{
   104  			name: "jiri package roller",
   105  			input: `rollers: [
   106  				{
   107  					jiri_packages: {
   108  						ref: "foo"
   109  						manifests: [
   110  							{
   111  								path: "path/to/jiri_manifest"
   112  								packages: [
   113  									"foo/package1/${platform}"
   114  								]
   115  							}
   116  						]
   117  					}
   118  				},
   119  				{
   120  					jiri_packages: {
   121  						manifests: [
   122  							{
   123  								path: "path/to/jiri_manifest"
   124  								packages: [
   125  									"foo/package2/${platform}"
   126  								]
   127  							}
   128  						]
   129  					}
   130  				}
   131  			]
   132  			default_checkout_jiri_manifest: "manifest"
   133  			`,
   134  			want: `[
   135  				{
   136  					"type": "jiri_packages",
   137  					"manifests": [
   138  						{
   139  							"path": "path/to/jiri_manifest",
   140  							"packages": [
   141  								"foo/package1/${platform}"
   142  							]
   143  						}
   144  					],
   145  					"ref": "foo",
   146  					"checkout_manifest": "manifest",
   147  					"schedule": "",
   148  					"force_submit": false,
   149  					"owner_email": "",
   150  					"notify_emails": []
   151  				},
   152  				{
   153  					"type": "jiri_packages",
   154  					"manifests": [
   155  						{
   156  							"path": "path/to/jiri_manifest",
   157  							"packages": [
   158  								"foo/package2/${platform}"
   159  							]
   160  						}
   161  					],
   162  					"ref": "latest",
   163  					"checkout_manifest": "manifest",
   164  					"schedule": "",
   165  					"force_submit": false,
   166  					"owner_email": "",
   167  					"notify_emails": []
   168  				}
   169  			]`,
   170  		},
   171  	}
   172  
   173  	for _, tc := range testCases {
   174  		tc := tc
   175  		t.Run(tc.name, func(t *testing.T) {
   176  			t.Parallel()
   177  
   178  			var config proto.Config
   179  			if err := prototext.Unmarshal([]byte(tc.input), &config); err != nil {
   180  				t.Fatal(err)
   181  			}
   182  
   183  			repoRoot := t.TempDir()
   184  			writeFiles(t, repoRoot, testFiles)
   185  
   186  			var output strings.Builder
   187  			if err := resolve(context.Background(), repoRoot, &config, &output); err != nil {
   188  				t.Fatal(err)
   189  			}
   190  
   191  			got := formatJSON(t, output.String())
   192  			want := formatJSON(t, tc.want)
   193  			if diff := cmp.Diff(want, got); diff != "" {
   194  				t.Errorf("Resolution diff (-want +got):\n%s", diff)
   195  			}
   196  		})
   197  	}
   198  }
   199  
   200  func formatJSON(t *testing.T, jsonStr string) string {
   201  	var m []map[string]any
   202  	if err := json.Unmarshal([]byte(jsonStr), &m); err != nil {
   203  		t.Fatal(err)
   204  	}
   205  	b, err := json.Marshal(m)
   206  	if err != nil {
   207  		t.Fatal(err)
   208  	}
   209  	return string(b)
   210  }