golang.org/x/build@v0.0.0-20240506185731-218518f32b70/internal/task/vscodego_test.go (about)

     1  // Copyright 2024 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package task
     6  
     7  import (
     8  	"bytes"
     9  	"context"
    10  	"os"
    11  	"path/filepath"
    12  	"strings"
    13  	"testing"
    14  
    15  	"github.com/google/go-cmp/cmp"
    16  	"github.com/google/go-cmp/cmp/cmpopts"
    17  	"golang.org/x/build/internal/workflow"
    18  )
    19  
    20  func TestVSCodeGoReleaseTask_buildVSCGO(t *testing.T) {
    21  	mustHaveShell(t)
    22  
    23  	tests := []struct {
    24  		name           string
    25  		revision       string
    26  		wantBuildError bool
    27  	}{
    28  		{
    29  			name:     "success",
    30  			revision: "release",
    31  		},
    32  		{
    33  			name:           "broken build",
    34  			revision:       "master", // broken
    35  			wantBuildError: true,
    36  		},
    37  	}
    38  
    39  	for _, test := range tests {
    40  		t.Run(test.name, func(t *testing.T) {
    41  			repo := NewFakeRepo(t, "vscode-go")
    42  			t1 := repo.Commit(map[string]string{
    43  				"go.mod":        "module github.com/golang/vscode-go\n",
    44  				"go.sum":        "\n",
    45  				"vscgo/main.go": "package main\nfunc main() { println(\"v1\") }\n",
    46  			})
    47  			repo.Branch("release", t1)
    48  
    49  			_ = repo.Commit(map[string]string{
    50  				"vscgo/broken.go": "package broken\n", // broken at master
    51  			})
    52  
    53  			gerrit := NewFakeGerrit(t, repo)
    54  			scratchDir := t.TempDir()
    55  
    56  			// fakeGo will record the invocation command in the fake output.
    57  			const fakeGo = `#!/bin/bash -eu
    58  
    59  function find_output_value() {
    60  	# returns -o flag value.
    61  	while [[ $# -gt 0 ]]; do
    62  	  case "$1" in
    63  		-o)
    64  		  if [[ $# -gt 1 ]]; then
    65  			echo "$2"
    66  			shift 2
    67  		  else
    68  			echo "Error: No argument provided after '-o'"
    69  			exit 1
    70  		  fi
    71  		  ;;
    72  		*)
    73  		  shift
    74  		  ;;
    75  	  esac
    76  	done
    77  }
    78  
    79  case "$1" in
    80  "build")
    81      if [[ -f "vscgo/broken.go" ]]; then
    82  	  echo build broken
    83  	  exit 1
    84  	fi
    85      out=$(find_output_value "$@")
    86  	echo "GOOS=${GOOS} GOARCH=${GOARCH} $0 $@" > "${out}"
    87  	exit 0
    88  	;;
    89  *)
    90  	echo unexpected command $@
    91  	;;
    92  esac
    93  `
    94  
    95  			releaseTask := &VSCodeGoReleaseTask{
    96  				CloudBuild: NewFakeCloudBuild(t, gerrit, "vscode-go", nil, fakeGo),
    97  				ScratchFS:  &ScratchFS{BaseURL: "file://" + scratchDir},
    98  				Revision:   test.revision,
    99  			}
   100  
   101  			wd := releaseTask.NewDefinition()
   102  			w, err := workflow.Start(wd, map[string]interface{}{
   103  				vscgoVersionParam.Name: "v0.0.0",
   104  			})
   105  			if err != nil {
   106  				t.Fatal(err)
   107  			}
   108  
   109  			ctx, cancel := context.WithCancel(context.Background())
   110  			defer cancel()
   111  
   112  			outputs, err := w.Run(ctx, &verboseListener{t: t, onStall: cancel})
   113  			if err != nil {
   114  				if test.wantBuildError {
   115  					return // expected build error.
   116  				}
   117  				t.Fatal(err)
   118  			}
   119  			buildArtifacts, ok := outputs["build artifacts"].([]goBuildArtifact)
   120  			if !ok {
   121  				t.Fatalf("unexpected build artifacts: %T (%+v): ", outputs, outputs)
   122  			}
   123  			var want []goBuildArtifact
   124  			for _, p := range vscgoPlatforms {
   125  				want = append(want, goBuildArtifact{
   126  					Platform: p.Platform,
   127  				})
   128  			}
   129  			sortSlice := cmpopts.SortSlices(func(x, y goBuildArtifact) bool { return x.Platform < y.Platform })
   130  			ignoreFilename := cmpopts.IgnoreFields(goBuildArtifact{}, "Filename")
   131  			if diff := cmp.Diff(buildArtifacts, want, sortSlice, ignoreFilename); diff != "" {
   132  				t.Fatal(diff)
   133  			}
   134  			// HACK: Reading directly from the scratch filesystem.
   135  			// XXX: is there a better way??
   136  			envMap := make(map[string][]string)
   137  			for _, p := range vscgoPlatforms {
   138  				envMap[p.Platform] = p.Env
   139  			}
   140  			for _, a := range buildArtifacts {
   141  				data, err := os.ReadFile(filepath.Join(scratchDir, w.ID.String(), a.Filename))
   142  				if err != nil {
   143  					t.Errorf("%v: %v", a.Platform, err)
   144  				}
   145  				envs := envMap[a.Platform]
   146  				if !bytes.Contains(data, []byte(strings.Join(envs, " "))) {
   147  					t.Errorf("%v: unexpected contents: %s", a.Platform, data)
   148  				}
   149  
   150  			}
   151  		})
   152  	}
   153  }