1// Copyright 2022 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
5package testing_test
6
7import (
8	"flag"
9	"internal/testenv"
10	"os"
11	"os/exec"
12	"testing"
13)
14
15var testFlagArg = flag.String("test_flag_arg", "", "TestFlag: passing -v option")
16
17const flagTestEnv = "GO_WANT_FLAG_HELPER_PROCESS"
18
19func TestFlag(t *testing.T) {
20	if os.Getenv(flagTestEnv) == "1" {
21		testFlagHelper(t)
22		return
23	}
24
25	testenv.MustHaveExec(t)
26
27	for _, flag := range []string{"", "-test.v", "-test.v=test2json"} {
28		flag := flag
29		t.Run(flag, func(t *testing.T) {
30			t.Parallel()
31			exe, err := os.Executable()
32			if err != nil {
33				exe = os.Args[0]
34			}
35			cmd := exec.Command(exe, "-test.run=^TestFlag$", "-test_flag_arg="+flag)
36			if flag != "" {
37				cmd.Args = append(cmd.Args, flag)
38			}
39			cmd.Env = append(cmd.Environ(), flagTestEnv+"=1")
40			b, err := cmd.CombinedOutput()
41			if len(b) > 0 {
42				// When we set -test.v=test2json, we need to escape the ^V control
43				// character used for JSON framing so that the JSON parser doesn't
44				// misinterpret the subprocess output as output from the parent test.
45				t.Logf("%q", b)
46			}
47			if err != nil {
48				t.Error(err)
49			}
50		})
51	}
52}
53
54// testFlagHelper is called by the TestFlagHelper subprocess.
55func testFlagHelper(t *testing.T) {
56	f := flag.Lookup("test.v")
57	if f == nil {
58		t.Fatal(`flag.Lookup("test.v") failed`)
59	}
60
61	bf, ok := f.Value.(interface{ IsBoolFlag() bool })
62	if !ok {
63		t.Errorf("test.v flag (type %T) does not have IsBoolFlag method", f)
64	} else if !bf.IsBoolFlag() {
65		t.Error("test.v IsBoolFlag() returned false")
66	}
67
68	gf, ok := f.Value.(flag.Getter)
69	if !ok {
70		t.Fatalf("test.v flag (type %T) does not have Get method", f)
71	}
72	v := gf.Get()
73
74	var want any
75	switch *testFlagArg {
76	case "":
77		want = false
78	case "-test.v":
79		want = true
80	case "-test.v=test2json":
81		want = "test2json"
82	default:
83		t.Fatalf("unexpected test_flag_arg %q", *testFlagArg)
84	}
85
86	if v != want {
87		t.Errorf("test.v is %v want %v", v, want)
88	}
89}
90