@@ -39,6 +39,9 @@ constexpr std::string_view kTestGoLittleEndiani386BinaryPath =
3939constexpr std::string_view kTestGoLittleEndianBinaryPath =
4040 " src/stirling/obj_tools/testdata/go/test_go_1_17_binary" ;
4141
42+ constexpr std::string_view kTestGoWithModulesBinaryPath =
43+ " src/stirling/obj_tools/testdata/go/test_buildinfo_with_mods" ;
44+
4245constexpr std::string_view kTestGoBinaryPath =
4346 " src/stirling/obj_tools/testdata/go/test_go_1_19_binary" ;
4447constexpr std::string_view kTestGo1_21BinaryPath =
@@ -47,25 +50,134 @@ constexpr std::string_view kTestGo1_21BinaryPath =
4750// The "endian agnostic" case refers to where the Go version data is varint encoded
4851// directly within the buildinfo header. See the following reference for more details.
4952// https://github.com/golang/go/blob/1dbbafc70fd3e2c284469ab3e0936c1bb56129f6/src/debug/buildinfo/buildinfo.go#L184C16-L184C16
50- TEST (ReadGoBuildVersionTest , BuildinfoEndianAgnostic) {
53+ TEST (ReadGoBuildInfoTest , BuildinfoEndianAgnostic) {
5154 const std::string kPath = px::testing::BazelRunfilePath (kTestGoBinaryPath );
5255 ASSERT_OK_AND_ASSIGN (std::unique_ptr<ElfReader> elf_reader, ElfReader::Create (kPath ));
53- ASSERT_OK_AND_ASSIGN (std::string version, ReadGoBuildVersion (elf_reader.get ()));
54- EXPECT_THAT (version, StrEq (" go1.19.13" ));
56+ ASSERT_OK_AND_ASSIGN (auto pair, ReadGoBuildInfo (elf_reader.get ()));
57+ auto version = pair.first ;
58+ EXPECT_THAT (version, StrEq (" 1.19.13" ));
5559}
5660
57- TEST (ReadGoBuildVersionTest , BuildinfoLittleEndian) {
61+ TEST (ReadGoBuildInfoTest , BuildinfoLittleEndian) {
5862 const std::string kPath = px::testing::BazelRunfilePath (kTestGoLittleEndianBinaryPath );
5963 ASSERT_OK_AND_ASSIGN (std::unique_ptr<ElfReader> elf_reader, ElfReader::Create (kPath ));
60- ASSERT_OK_AND_ASSIGN (std::string version, ReadGoBuildVersion (elf_reader.get ()));
61- EXPECT_THAT (version, StrEq (" go1.17.13" ));
64+ ASSERT_OK_AND_ASSIGN (auto pair, ReadGoBuildInfo (elf_reader.get ()));
65+ auto version = pair.first ;
66+ EXPECT_THAT (version, StrEq (" 1.17.13" ));
67+ }
68+
69+ // These tests are modeled off of upstream's
70+ // https://github.com/golang/go/blob/93fb2c90740aef00553c9ce6a7cd4578c2469675/src/runtime/debug/mod_test.go#L23
71+ TEST (ReadGoBuildInfoTest, BuildinfoPackageBuiltOutsideModule) {
72+ const std::string kBinContent =
73+ " path\t rsc.io/fortune\n "
74+ " mod\t rsc.io/fortune\t v1.0.0" ;
75+ auto build_info_s = ReadModInfo (kBinContent );
76+ EXPECT_OK (build_info_s);
77+
78+ auto build_info = build_info_s.ConsumeValueOrDie ();
79+ EXPECT_EQ (build_info.path , " rsc.io/fortune" );
80+ EXPECT_EQ (build_info.main .path , " rsc.io/fortune" );
81+ EXPECT_EQ (build_info.main .version , " v1.0.0" );
82+ }
83+
84+ TEST (ReadGoBuildInfoTest, BuildinfoPackageBuiltStdlib) {
85+ const std::string kBinContent = " path\t cmd/test2json" ;
86+ auto build_info_s = ReadModInfo (kBinContent );
87+ EXPECT_OK (build_info_s);
88+ auto build_info = build_info_s.ConsumeValueOrDie ();
89+ EXPECT_EQ (build_info.path , " cmd/test2json" );
90+ }
91+
92+ TEST (ReadGoBuildInfoTest, BuildinfoPackageBuiltInsideModule) {
93+ const std::string kBinContent =
94+ " go\t 1.18\n "
95+ " path\t example.com/m\n "
96+ " mod\t example.com/m\t (devel)\n "
97+ " build\t -compiler=gc" ;
98+ auto build_info_s = ReadModInfo (kBinContent );
99+ EXPECT_OK (build_info_s);
100+
101+ auto build_info = build_info_s.ConsumeValueOrDie ();
102+ EXPECT_EQ (build_info.path , " example.com/m" );
103+ EXPECT_EQ (build_info.main .path , " example.com/m" );
104+ EXPECT_EQ (build_info.main .version , " (devel)" );
105+ EXPECT_EQ (build_info.main .replace , nullptr );
106+ EXPECT_EQ (build_info.deps .size (), 0 );
107+ }
108+
109+ TEST (ReadGoBuildInfoTest, BuildinfoWithModules) {
110+ const std::string kPath = px::testing::BazelRunfilePath (kTestGoWithModulesBinaryPath );
111+ ASSERT_OK_AND_ASSIGN (std::unique_ptr<ElfReader> elf_reader, ElfReader::Create (kPath ));
112+ ASSERT_OK_AND_ASSIGN (auto pair, ReadGoBuildInfo (elf_reader.get ()));
113+ auto version = pair.first ;
114+ EXPECT_THAT (version, StrEq (" 1.23.0" ));
115+
116+ auto & build_info = pair.second ;
117+ // Validate main module path.
118+ EXPECT_THAT (build_info.path ,
119+ StrEq (" go.opentelemetry.io/auto/internal/tools/inspect/cmd/offsetgen" ));
120+
121+ // Validate main module metadata.
122+ EXPECT_THAT (build_info.main .path , StrEq (" go.opentelemetry.io/auto/internal/tools" ));
123+ EXPECT_THAT (build_info.main .version , StrEq (" (devel)" ));
124+ EXPECT_EQ (build_info.main .replace , nullptr );
125+
126+ // Validate module dependencies.
127+ EXPECT_THAT (build_info.deps ,
128+ UnorderedElementsAre (
129+ Field (&Module::path, StrEq (" github.com/Masterminds/semver/v3" )),
130+ Field (&Module::path, StrEq (" github.com/cilium/ebpf" )),
131+ Field (&Module::path, StrEq (" github.com/distribution/reference" )),
132+ Field (&Module::path, StrEq (" github.com/docker/docker" )),
133+ Field (&Module::path, StrEq (" github.com/docker/go-connections" )),
134+ Field (&Module::path, StrEq (" github.com/docker/go-units" )),
135+ Field (&Module::path, StrEq (" github.com/felixge/httpsnoop" )),
136+ Field (&Module::path, StrEq (" github.com/go-logr/logr" )),
137+ Field (&Module::path, StrEq (" github.com/go-logr/stdr" )),
138+ Field (&Module::path, StrEq (" github.com/gogo/protobuf" )),
139+ Field (&Module::path, StrEq (" github.com/moby/docker-image-spec" )),
140+ Field (&Module::path, StrEq (" github.com/opencontainers/go-digest" )),
141+ Field (&Module::path, StrEq (" github.com/opencontainers/image-spec" )),
142+ Field (&Module::path, StrEq (" github.com/pkg/errors" )),
143+ Field (&Module::path, StrEq (" go.opentelemetry.io/auto" )),
144+ Field (&Module::path, StrEq (" go.opentelemetry.io/auto/sdk" )),
145+ Field (&Module::path, StrEq (" go.opentelemetry.io/collector/pdata" )),
146+ Field (&Module::path,
147+ StrEq (" go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" )),
148+ Field (&Module::path, StrEq (" go.opentelemetry.io/otel" )),
149+ Field (&Module::path, StrEq (" go.opentelemetry.io/otel/metric" )),
150+ Field (&Module::path, StrEq (" go.opentelemetry.io/otel/trace" )),
151+ Field (&Module::path, StrEq (" go.uber.org/multierr" )),
152+ Field (&Module::path, StrEq (" golang.org/x/arch" )),
153+ Field (&Module::path, StrEq (" golang.org/x/net" )),
154+ Field (&Module::path, StrEq (" golang.org/x/sync" )),
155+ Field (&Module::path, StrEq (" golang.org/x/sys" )),
156+ Field (&Module::path, StrEq (" golang.org/x/text" )),
157+ Field (&Module::path, StrEq (" google.golang.org/genproto/googleapis/rpc" )),
158+ Field (&Module::path, StrEq (" google.golang.org/grpc" )),
159+ Field (&Module::path, StrEq (" google.golang.org/protobuf" ))));
160+
161+ // Validate replaced modules.
162+ EXPECT_THAT (build_info.deps ,
163+ Contains (AllOf (Field (&Module::path, StrEq (" go.opentelemetry.io/auto" )),
164+ Field (&Module::replace,
165+ Pointee (AllOf (Field (&Module::path, StrEq (" ../../" )),
166+ Field (&Module::version, StrEq (" (devel)" ))))))));
167+
168+ EXPECT_THAT (build_info.deps ,
169+ Contains (AllOf (Field (&Module::path, StrEq (" go.opentelemetry.io/auto/sdk" )),
170+ Field (&Module::replace,
171+ Pointee (AllOf (Field (&Module::path, StrEq (" ../../sdk" )),
172+ Field (&Module::version, StrEq (" (devel)" ))))))));
62173}
63174
64- TEST (ReadGoBuildVersionTest , BuildinfoLittleEndiani386) {
175+ TEST (ReadGoBuildInfoTest , BuildinfoLittleEndiani386) {
65176 const std::string kPath = px::testing::BazelRunfilePath (kTestGoLittleEndiani386BinaryPath );
66177 ASSERT_OK_AND_ASSIGN (std::unique_ptr<ElfReader> elf_reader, ElfReader::Create (kPath ));
67- ASSERT_OK_AND_ASSIGN (std::string version, ReadGoBuildVersion (elf_reader.get ()));
68- EXPECT_THAT (version, StrEq (" go1.13.15" ));
178+ ASSERT_OK_AND_ASSIGN (auto pair, ReadGoBuildInfo (elf_reader.get ()));
179+ auto version = pair.first ;
180+ EXPECT_THAT (version, StrEq (" 1.13.15" ));
69181}
70182
71183TEST (IsGoExecutableTest, WorkingOnBasicGoBinary) {
0 commit comments