# Note that this is the only test with a module where we rely on the detection # of GOPRIVATE. # Also note that, since this is the only test using "real" external modules # fetched via GOPROXY, go.mod and go.sum should declare the dependencies. # For now, use a throwaway module download cache instead of the host machine's. # Usually it would be fine to reuse the host's, since we expose exact copies of # some external modules in a local proxy, allowing 'go test' to work offline. # However, for some reason, we end up with different hashes of the code for # modules like rsc.io/quote, and it's unclear why. It might be a txtar-addmod bug. # In any case, not worth our time to investigate right now, and "downloading" # modules is instant since we just copy a handful of files. # # To reproduce the issue, remove the env line and run: # # go clean -modcache && go get -d rsc.io/quote@v1.5.2 && go test -short env GOMODCACHE=$WORK/modcache garble build -tags buildtag exec ./main cmp stdout main.stdout ! binsubstr main$exe 'ImportedVar' 'ImportedConst' 'ImportedFunc' 'ImportedType' 'main.go' 'test/main' 'importedpkg.' 'NormalStruct' 'NormalExportedField' 'normalUnexportedField' binsubstr main$exe 'ReflectInDefined' 'ExportedField2' 'unexportedField2' [short] stop # checking that the build is reproducible is slow # Also check that the binary is reproducible when many imports are involved. # No packages should be rebuilt either, thanks to the build cache. cp main$exe main_old$exe rm main$exe garble build -tags buildtag -v ! stderr . bincmp main$exe main_old$exe go build -tags buildtag exec ./main cmp stdout main.stdout # Also check that -literals doesn't break anything garble -literals build -tags buildtag exec ./main cmp stdout main.stdout -- go.mod -- module test/main go 1.15 require ( rsc.io/quote v1.5.2 gopkg.in/garbletest.v2 v2.999.0 ) -- go.sum -- golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/garbletest.v2 v2.999.0 h1:wiZfOKGiXX7DoYVgbNvnTaCjqElrpZQSvKg0HYouw/o= gopkg.in/garbletest.v2 v2.999.0/go.mod h1:MF1BPTBjmDdc9x86+9UMLL9pAH2eMFPHvltohOvlGEw= rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0= rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -- main.go -- package main import ( "fmt" "reflect" "strings" "test/main/importedpkg" "rsc.io/quote" garbletest "gopkg.in/garbletest.v2" ) func main() { fmt.Println(importedpkg.ImportedVar) fmt.Println(importedpkg.ImportedConst) fmt.Println(importedpkg.ImportedFunc('x')) fmt.Println(importedpkg.ImportedType(3)) fmt.Println(importedpkg.ReflectInDefinedVar.ExportedField2) fmt.Println(importedpkg.ReflectInDefined{ExportedField2: 5}) normal := importedpkg.NormalStruct{SharedName: 3} normal.IndirectStruct.Field = 23 fmt.Println(normal) printfWithoutPackage("%T\n", importedpkg.ReflectTypeOf(2)) printfWithoutPackage("%T\n", importedpkg.ReflectTypeOfIndirect(4)) v := importedpkg.ReflectValueOfVar printfWithoutPackage("%#v\n", v) method := reflect.ValueOf(&v).MethodByName("ExportedMethodName") if method.IsValid() { fmt.Println(method.Call(nil)) } else { fmt.Println("method not found") } fmt.Println(quote.Go()) garbletest.Test() } func printfWithoutPackage(format string, v interface{}) { fmt.Print(strings.Split(fmt.Sprintf(format, v), ".")[1]) } -- notag_fail.go -- // +build !buildtag package main var foo int = "should be omitted by -tags" -- withtag_success.go -- // +build buildtag package main import "fmt" func init() { fmt.Println("buildtag init func") } -- importedpkg/imported.go -- package importedpkg import ( "reflect" "test/main/importedpkg/indirect" ) var ImportedVar = "imported var value" const ImportedConst = "imported const value" func ImportedFunc(param rune) string { return string(param) } type ReflectTypeOf int var _ = reflect.TypeOf(ReflectTypeOf(0)) type ReflectTypeOfIndirect int var _ = reflect.TypeOf(new([]*ReflectTypeOfIndirect)) type ReflectValueOf struct { ExportedField string unexportedField string } func (r *ReflectValueOf) ExportedMethodName() string { return "method: " + r.ExportedField } var ReflectValueOfVar = ReflectValueOf{ExportedField: "abc"} var _ = reflect.TypeOf(ReflectValueOfVar) type ReflectInDefined struct { ExportedField2 int unexportedField2 int } var ReflectInDefinedVar = ReflectInDefined{ExportedField2: 9000} var _ = reflect.TypeOf(ReflectInDefinedVar) const SharedName = 2 type NormalStruct struct { SharedName int IndirectStruct indirect.Indirect normalUnexportedField int } // ImportedType comes after the calls to reflect, to ensure no false positives. type ImportedType int -- importedpkg/indirect/indirect.go -- package indirect type Indirect struct { Field int } -- main.stdout -- buildtag init func imported var value imported const value x 3 9000 {5 0} {3 {23} 0} ReflectTypeOf ReflectTypeOfIndirect ReflectValueOf{ExportedField:"abc", unexportedField:""} [method: abc] Don't communicate by sharing memory, share memory by communicating.