blob: 757d41067661b893b8542d528a29a279bc45c6b4 [file] [log] [blame]
Joe Tsai707894e2019-03-01 12:50:52 -08001// Copyright 2019 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
Joe Tsaif3987842019-03-02 13:35:17 -08005// +build ignore
Joe Tsai707894e2019-03-01 12:50:52 -08006
Joe Tsaif3987842019-03-02 13:35:17 -08007package main
Joe Tsai707894e2019-03-01 12:50:52 -08008
9import (
10 "archive/tar"
11 "bytes"
12 "compress/gzip"
13 "flag"
14 "fmt"
15 "io"
16 "io/ioutil"
17 "net/http"
18 "os"
19 "os/exec"
20 "path/filepath"
Damien Neil3a185602020-02-21 09:16:19 -080021 "regexp"
Joe Tsai707894e2019-03-01 12:50:52 -080022 "runtime"
23 "strings"
Joe Tsai62200db2019-07-11 17:34:10 -070024 "sync"
Joe Tsai707894e2019-03-01 12:50:52 -080025 "testing"
Joe Tsaif3987842019-03-02 13:35:17 -080026 "time"
Joe Tsai4f3de442019-08-07 19:33:51 -070027
28 "google.golang.org/protobuf/runtime/protoimpl"
Joe Tsai707894e2019-03-01 12:50:52 -080029)
30
31var (
Joe Tsai4f3de442019-08-07 19:33:51 -070032 regenerate = flag.Bool("regenerate", false, "regenerate files")
33 buildRelease = flag.Bool("buildRelease", false, "build release binaries")
Joe Tsai707894e2019-03-01 12:50:52 -080034
Joe Tsaiabd06a82019-08-16 00:39:27 -070035 protobufVersion = "3.9.1"
Herbie Ong39246252019-09-06 11:20:30 -070036 golangVersions = []string{"1.9.7", "1.10.8", "1.11.13", "1.12.9", "1.13"}
Joe Tsai707894e2019-03-01 12:50:52 -080037 golangLatest = golangVersions[len(golangVersions)-1]
38
Joe Tsai9e88bc02019-03-12 01:30:40 -070039 // purgeTimeout determines the maximum age of unused sub-directories.
40 purgeTimeout = 30 * 24 * time.Hour // 1 month
Joe Tsai707894e2019-03-01 12:50:52 -080041
42 // Variables initialized by mustInitDeps.
Herbie Ongd64dceb2019-04-25 01:19:57 -070043 goPath string
44 modulePath string
45 protobufPath string
Joe Tsai707894e2019-03-01 12:50:52 -080046)
47
48func Test(t *testing.T) {
49 mustInitDeps(t)
Joe Tsai4f3de442019-08-07 19:33:51 -070050 mustHandleFlags(t)
Joe Tsai707894e2019-03-01 12:50:52 -080051
Joe Tsai62200db2019-07-11 17:34:10 -070052 var wg sync.WaitGroup
53 sema := make(chan bool, (runtime.NumCPU()+1)/2)
54 for i := range golangVersions {
55 goVersion := golangVersions[i]
56 goLabel := "Go" + goVersion
57 runGo := func(label, workDir string, args ...string) {
58 wg.Add(1)
59 sema <- true
60 go func() {
61 defer wg.Done()
62 defer func() { <-sema }()
63 t.Run(goLabel+"/"+label, func(t *testing.T) {
64 args[0] += goVersion
Joe Tsai7164af52019-08-07 19:27:43 -070065 command{Dir: workDir}.mustRun(t, args...)
Joe Tsai707894e2019-03-01 12:50:52 -080066 })
Joe Tsai62200db2019-07-11 17:34:10 -070067 }()
68 }
69
70 workDir := filepath.Join(goPath, "src", modulePath)
71 runGo("Normal", workDir, "go", "test", "-race", "./...")
72 runGo("PureGo", workDir, "go", "test", "-race", "-tags", "purego", "./...")
73 runGo("Reflect", workDir, "go", "test", "-race", "-tags", "protoreflect", "./...")
74 if goVersion == golangLatest {
Joe Tsai1799d112019-08-08 13:31:59 -070075 runGo("ProtoLegacy", workDir, "go", "test", "-race", "-tags", "protolegacy", "./...")
Joe Tsai62200db2019-07-11 17:34:10 -070076 runGo("ProtocGenGo", "cmd/protoc-gen-go/testdata", "go", "test")
Joe Tsaidd271b62019-08-16 01:09:33 -070077 runGo("Conformance", "internal/conformance", "go", "test", "-execute")
Joe Tsai62200db2019-07-11 17:34:10 -070078 }
Joe Tsai707894e2019-03-01 12:50:52 -080079 }
Joe Tsai62200db2019-07-11 17:34:10 -070080 wg.Wait()
Joe Tsai707894e2019-03-01 12:50:52 -080081
82 t.Run("GeneratedGoFiles", func(t *testing.T) {
Joe Tsai1799d112019-08-08 13:31:59 -070083 diff := mustRunCommand(t, "go", "run", "-tags", "protolegacy", "./internal/cmd/generate-types")
Joe Tsai707894e2019-03-01 12:50:52 -080084 if strings.TrimSpace(diff) != "" {
85 t.Fatalf("stale generated files:\n%v", diff)
86 }
Joe Tsai1799d112019-08-08 13:31:59 -070087 diff = mustRunCommand(t, "go", "run", "-tags", "protolegacy", "./internal/cmd/generate-protos")
Joe Tsai707894e2019-03-01 12:50:52 -080088 if strings.TrimSpace(diff) != "" {
89 t.Fatalf("stale generated files:\n%v", diff)
90 }
91 })
92 t.Run("FormattedGoFiles", func(t *testing.T) {
Joe Tsai7164af52019-08-07 19:27:43 -070093 files := strings.Split(strings.TrimSpace(mustRunCommand(t, "git", "ls-files", "*.go")), "\n")
94 diff := mustRunCommand(t, append([]string{"gofmt", "-d"}, files...)...)
Joe Tsai707894e2019-03-01 12:50:52 -080095 if strings.TrimSpace(diff) != "" {
96 t.Fatalf("unformatted source files:\n%v", diff)
97 }
98 })
Damien Neil3a185602020-02-21 09:16:19 -080099 t.Run("CopyrightHeaders", func(t *testing.T) {
100 files := strings.Split(strings.TrimSpace(mustRunCommand(t, "git", "ls-files", "*.go", "*.proto")), "\n")
101 mustHaveCopyrightHeader(t, files)
102 })
Joe Tsai707894e2019-03-01 12:50:52 -0800103 t.Run("CommittedGitChanges", func(t *testing.T) {
Joe Tsai7164af52019-08-07 19:27:43 -0700104 diff := mustRunCommand(t, "git", "diff", "--no-prefix", "HEAD")
Joe Tsai707894e2019-03-01 12:50:52 -0800105 if strings.TrimSpace(diff) != "" {
106 t.Fatalf("uncommitted changes:\n%v", diff)
107 }
108 })
109 t.Run("TrackedGitFiles", func(t *testing.T) {
Joe Tsai7164af52019-08-07 19:27:43 -0700110 diff := mustRunCommand(t, "git", "ls-files", "--others", "--exclude-standard")
Joe Tsai707894e2019-03-01 12:50:52 -0800111 if strings.TrimSpace(diff) != "" {
112 t.Fatalf("untracked files:\n%v", diff)
113 }
114 })
115}
116
117func mustInitDeps(t *testing.T) {
118 check := func(err error) {
119 t.Helper()
120 if err != nil {
121 t.Fatal(err)
122 }
123 }
124
125 // Determine the directory to place the test directory.
126 repoRoot, err := os.Getwd()
127 check(err)
128 testDir := filepath.Join(repoRoot, ".cache")
129 check(os.MkdirAll(testDir, 0775))
130
Joe Tsaif3987842019-03-02 13:35:17 -0800131 // Travis-CI has a hard-coded timeout where it kills the test after
132 // 10 minutes of a lack of activity on stdout.
133 // We work around this restriction by periodically printing the timestamp.
134 ticker := time.NewTicker(5 * time.Minute)
135 done := make(chan struct{})
136 go func() {
137 now := time.Now()
138 for {
139 select {
140 case t := <-ticker.C:
141 fmt.Printf("\tt=%0.fmin\n", t.Sub(now).Minutes())
142 case <-done:
143 return
144 }
145 }
146 }()
147 defer close(done)
148 defer ticker.Stop()
149
Joe Tsai707894e2019-03-01 12:50:52 -0800150 // Delete the current directory if non-empty,
151 // which only occurs if a dependency failed to initialize properly.
152 var workingDir string
153 defer func() {
154 if workingDir != "" {
155 os.RemoveAll(workingDir) // best-effort
156 }
157 }()
158
159 // Delete other sub-directories that are no longer relevant.
160 defer func() {
161 subDirs := map[string]bool{"bin": true, "gocache": true, "gopath": true}
162 subDirs["protobuf-"+protobufVersion] = true
163 for _, v := range golangVersions {
164 subDirs["go"+v] = true
165 }
Joe Tsai707894e2019-03-01 12:50:52 -0800166
Joe Tsai9e88bc02019-03-12 01:30:40 -0700167 now := time.Now()
Joe Tsai707894e2019-03-01 12:50:52 -0800168 fis, _ := ioutil.ReadDir(testDir)
169 for _, fi := range fis {
Joe Tsai9e88bc02019-03-12 01:30:40 -0700170 if subDirs[fi.Name()] {
171 os.Chtimes(filepath.Join(testDir, fi.Name()), now, now) // best-effort
172 continue
Joe Tsai707894e2019-03-01 12:50:52 -0800173 }
Joe Tsai9e88bc02019-03-12 01:30:40 -0700174 if now.Sub(fi.ModTime()) < purgeTimeout {
175 continue
176 }
177 fmt.Printf("delete %v\n", fi.Name())
178 os.RemoveAll(filepath.Join(testDir, fi.Name())) // best-effort
Joe Tsai707894e2019-03-01 12:50:52 -0800179 }
180 }()
181
182 // The bin directory contains symlinks to each tool by version.
183 // It is safe to delete this directory and run the test script from scratch.
184 binPath := filepath.Join(testDir, "bin")
185 check(os.RemoveAll(binPath))
186 check(os.Mkdir(binPath, 0775))
187 check(os.Setenv("PATH", binPath+":"+os.Getenv("PATH")))
188 registerBinary := func(name, path string) {
189 check(os.Symlink(path, filepath.Join(binPath, name)))
190 }
191
192 // Download and build the protobuf toolchain.
193 // We avoid downloading the pre-compiled binaries since they do not contain
194 // the conformance test runner.
195 workingDir = filepath.Join(testDir, "protobuf-"+protobufVersion)
Herbie Ongd64dceb2019-04-25 01:19:57 -0700196 protobufPath = workingDir
197 if _, err := os.Stat(protobufPath); err != nil {
198 fmt.Printf("download %v\n", filepath.Base(protobufPath))
Joe Tsai707894e2019-03-01 12:50:52 -0800199 url := fmt.Sprintf("https://github.com/google/protobuf/releases/download/v%v/protobuf-all-%v.tar.gz", protobufVersion, protobufVersion)
Herbie Ongd64dceb2019-04-25 01:19:57 -0700200 downloadArchive(check, protobufPath, url, "protobuf-"+protobufVersion)
Joe Tsai707894e2019-03-01 12:50:52 -0800201
Herbie Ongd64dceb2019-04-25 01:19:57 -0700202 fmt.Printf("build %v\n", filepath.Base(protobufPath))
Joe Tsai7164af52019-08-07 19:27:43 -0700203 command{Dir: protobufPath}.mustRun(t, "./autogen.sh")
204 command{Dir: protobufPath}.mustRun(t, "./configure")
205 command{Dir: protobufPath}.mustRun(t, "make")
206 command{Dir: filepath.Join(protobufPath, "conformance")}.mustRun(t, "make")
Joe Tsai707894e2019-03-01 12:50:52 -0800207 }
Damien Neila80229e2019-06-20 12:53:48 -0700208 // The benchmark directory isn't present in the release download,
209 // so fetch needed files directly.
210 for _, path := range benchmarkProtos {
211 src := fmt.Sprintf("https://raw.githubusercontent.com/protocolbuffers/protobuf/v%v/%v", protobufVersion, path)
212 dst := filepath.Join(protobufPath, path)
213 if _, err := os.Stat(dst); err != nil {
214 downloadFile(check, dst, src)
215 }
216 }
217 benchdataPath := filepath.Join(testDir, "benchdata")
218 for _, path := range []string{
219 "benchmarks/datasets/google_message1/proto2/dataset.google_message1_proto2.pb",
220 "benchmarks/datasets/google_message1/proto3/dataset.google_message1_proto3.pb",
221 "benchmarks/datasets/google_message2/dataset.google_message2.pb",
222 } {
223 src := fmt.Sprintf("https://raw.githubusercontent.com/protocolbuffers/protobuf/v%v/%v", protobufVersion, path)
224 dst := filepath.Join(benchdataPath, filepath.Base(path))
225 if _, err := os.Stat(dst); err != nil {
226 downloadFile(check, dst, src)
227 }
228 }
Herbie Ongd64dceb2019-04-25 01:19:57 -0700229 check(os.Setenv("PROTOBUF_ROOT", protobufPath)) // for generate-protos
230 registerBinary("conform-test-runner", filepath.Join(protobufPath, "conformance", "conformance-test-runner"))
231 registerBinary("protoc", filepath.Join(protobufPath, "src", "protoc"))
Joe Tsai707894e2019-03-01 12:50:52 -0800232 workingDir = ""
233
234 // Download each Go toolchain version.
235 for _, v := range golangVersions {
236 workingDir = filepath.Join(testDir, "go"+v)
237 if _, err := os.Stat(workingDir); err != nil {
238 fmt.Printf("download %v\n", filepath.Base(workingDir))
239 url := fmt.Sprintf("https://dl.google.com/go/go%v.%v-%v.tar.gz", v, runtime.GOOS, runtime.GOARCH)
Joe Tsaif3987842019-03-02 13:35:17 -0800240 downloadArchive(check, workingDir, url, "go")
Joe Tsai707894e2019-03-01 12:50:52 -0800241 }
242 registerBinary("go"+v, filepath.Join(workingDir, "bin", "go"))
243 }
244 registerBinary("go", filepath.Join(testDir, "go"+golangLatest, "bin", "go"))
245 registerBinary("gofmt", filepath.Join(testDir, "go"+golangLatest, "bin", "gofmt"))
246 workingDir = ""
247
248 // Travis-CI sets GOROOT, which confuses invocations of the Go toolchain.
249 // Explicitly clear GOROOT, so each toolchain uses their default GOROOT.
250 check(os.Unsetenv("GOROOT"))
251
Joe Tsai6a2180f2019-07-11 16:34:17 -0700252 // Set a cache directory outside the test directory.
253 check(os.Setenv("GOCACHE", filepath.Join(repoRoot, ".gocache")))
Joe Tsai707894e2019-03-01 12:50:52 -0800254
255 // Setup GOPATH for pre-module support (i.e., go1.10 and earlier).
256 goPath = filepath.Join(testDir, "gopath")
Joe Tsai7164af52019-08-07 19:27:43 -0700257 modulePath = strings.TrimSpace(command{Dir: testDir}.mustRun(t, "go", "list", "-m", "-f", "{{.Path}}"))
Joe Tsai707894e2019-03-01 12:50:52 -0800258 check(os.RemoveAll(filepath.Join(goPath, "src")))
259 check(os.MkdirAll(filepath.Join(goPath, "src", filepath.Dir(modulePath)), 0775))
260 check(os.Symlink(repoRoot, filepath.Join(goPath, "src", modulePath)))
Joe Tsai7164af52019-08-07 19:27:43 -0700261 command{Dir: repoRoot}.mustRun(t, "go", "mod", "tidy")
262 command{Dir: repoRoot}.mustRun(t, "go", "mod", "vendor")
Joe Tsai707894e2019-03-01 12:50:52 -0800263 check(os.Setenv("GOPATH", goPath))
264}
265
Damien Neila80229e2019-06-20 12:53:48 -0700266func downloadFile(check func(error), dstPath, srcURL string) {
267 resp, err := http.Get(srcURL)
268 check(err)
269 defer resp.Body.Close()
270
271 check(os.MkdirAll(filepath.Dir(dstPath), 0775))
272 f, err := os.Create(dstPath)
273 check(err)
274
275 _, err = io.Copy(f, resp.Body)
276 check(err)
277}
278
Joe Tsaif3987842019-03-02 13:35:17 -0800279func downloadArchive(check func(error), dstPath, srcURL, skipPrefix string) {
Joe Tsai707894e2019-03-01 12:50:52 -0800280 check(os.RemoveAll(dstPath))
281
282 resp, err := http.Get(srcURL)
283 check(err)
284 defer resp.Body.Close()
285
286 zr, err := gzip.NewReader(resp.Body)
287 check(err)
288
289 tr := tar.NewReader(zr)
290 for {
291 h, err := tr.Next()
292 if err == io.EOF {
293 return
294 }
295 check(err)
296
Joe Tsaif3987842019-03-02 13:35:17 -0800297 // Skip directories or files outside the prefix directory.
298 if len(skipPrefix) > 0 {
299 if !strings.HasPrefix(h.Name, skipPrefix) {
300 continue
301 }
302 if len(h.Name) > len(skipPrefix) && h.Name[len(skipPrefix)] != '/' {
303 continue
304 }
305 }
306
307 path := strings.TrimPrefix(strings.TrimPrefix(h.Name, skipPrefix), "/")
Joe Tsai707894e2019-03-01 12:50:52 -0800308 path = filepath.Join(dstPath, filepath.FromSlash(path))
309 mode := os.FileMode(h.Mode & 0777)
310 switch h.Typeflag {
311 case tar.TypeReg:
312 b, err := ioutil.ReadAll(tr)
313 check(err)
314 check(ioutil.WriteFile(path, b, mode))
315 case tar.TypeDir:
316 check(os.Mkdir(path, mode))
317 }
318 }
319}
320
Joe Tsai4f3de442019-08-07 19:33:51 -0700321func mustHandleFlags(t *testing.T) {
322 if *regenerate {
323 t.Run("Generate", func(t *testing.T) {
324 fmt.Print(mustRunCommand(t, "go", "run", "-tags", "protolegacy", "./internal/cmd/generate-types", "-execute"))
325 fmt.Print(mustRunCommand(t, "go", "run", "-tags", "protolegacy", "./internal/cmd/generate-protos", "-execute"))
326 files := strings.Split(strings.TrimSpace(mustRunCommand(t, "git", "ls-files", "*.go")), "\n")
327 mustRunCommand(t, append([]string{"gofmt", "-w"}, files...)...)
328 })
329 }
330 if *buildRelease {
331 t.Run("BuildRelease", func(t *testing.T) {
332 v := protoimpl.VersionString()
333 for _, goos := range []string{"linux", "darwin", "windows"} {
334 for _, goarch := range []string{"386", "amd64"} {
335 binPath := filepath.Join("bin", fmt.Sprintf("protoc-gen-go.%v.%v.%v", v, goos, goarch))
336
337 // Build the binary.
338 cmd := command{Env: append(os.Environ(), "GOOS="+goos, "GOARCH="+goarch)}
Joe Tsai576cfb32019-09-04 22:50:42 -0700339 cmd.mustRun(t, "go", "build", "-trimpath", "-ldflags", "-s -w -buildid=", "-o", binPath, "./cmd/protoc-gen-go")
Joe Tsai4f3de442019-08-07 19:33:51 -0700340
341 // Archive and compress the binary.
342 in, err := ioutil.ReadFile(binPath)
343 if err != nil {
344 t.Fatal(err)
345 }
346 out := new(bytes.Buffer)
347 gz, _ := gzip.NewWriterLevel(out, gzip.BestCompression)
348 gz.Comment = fmt.Sprintf("protoc-gen-go VERSION=%v GOOS=%v GOARCH=%v", v, goos, goarch)
349 tw := tar.NewWriter(gz)
350 tw.WriteHeader(&tar.Header{
351 Name: "protoc-gen-go",
352 Mode: int64(0775),
353 Size: int64(len(in)),
354 })
355 tw.Write(in)
356 tw.Close()
357 gz.Close()
358 if err := ioutil.WriteFile(binPath+".tar.gz", out.Bytes(), 0664); err != nil {
359 t.Fatal(err)
360 }
361 }
362 }
363 })
364 }
365 if *regenerate || *buildRelease {
366 t.SkipNow()
367 }
368}
369
Damien Neil3a185602020-02-21 09:16:19 -0800370var copyrightRegex = []*regexp.Regexp{
371 regexp.MustCompile(`^// Copyright \d\d\d\d The Go Authors\. All rights reserved.
372// Use of this source code is governed by a BSD-style
373// license that can be found in the LICENSE file\.
374`),
375 // Generated .pb.go files from main protobuf repo.
376 regexp.MustCompile(`^// Protocol Buffers - Google's data interchange format
377// Copyright \d\d\d\d Google Inc\. All rights reserved\.
378`),
379}
380
381var noCopyrightHeader = []string{
382 // Missing copyright header upstream.
383 "internal/testprotos/benchmarks/datasets/",
384}
385
386func mustHaveCopyrightHeader(t *testing.T, files []string) {
387 var bad []string
388File:
389 for _, file := range files {
390 for _, prefix := range noCopyrightHeader {
391 if strings.HasPrefix(file, prefix) {
392 continue File
393 }
394 }
395 b, err := ioutil.ReadFile(file)
396 if err != nil {
397 t.Fatal(err)
398 }
399 for _, re := range copyrightRegex {
400 if loc := re.FindIndex(b); loc != nil && loc[0] == 0 {
401 continue File
402 }
403 }
404 bad = append(bad, file)
405 }
406 if len(bad) > 0 {
407 t.Fatalf("files with missing/bad copyright headers:\n %v", strings.Join(bad, "\n "))
408 }
409}
410
Joe Tsai7164af52019-08-07 19:27:43 -0700411type command struct {
412 Dir string
413 Env []string
414}
415
416func (c command) mustRun(t *testing.T, args ...string) string {
Joe Tsai707894e2019-03-01 12:50:52 -0800417 t.Helper()
418 stdout := new(bytes.Buffer)
Herbie Ong4630b3d2019-03-19 16:42:01 -0700419 stderr := new(bytes.Buffer)
Joe Tsai707894e2019-03-01 12:50:52 -0800420 cmd := exec.Command(args[0], args[1:]...)
Joe Tsai7164af52019-08-07 19:27:43 -0700421 cmd.Dir = "."
422 if c.Dir != "" {
423 cmd.Dir = c.Dir
424 }
425 cmd.Env = os.Environ()
426 if c.Env != nil {
427 cmd.Env = c.Env
428 }
429 cmd.Env = append(cmd.Env, "PWD="+cmd.Dir)
Herbie Ong4630b3d2019-03-19 16:42:01 -0700430 cmd.Stdout = stdout
431 cmd.Stderr = stderr
Joe Tsai707894e2019-03-01 12:50:52 -0800432 if err := cmd.Run(); err != nil {
Herbie Ong4630b3d2019-03-19 16:42:01 -0700433 t.Fatalf("executing (%v): %v\n%s%s", strings.Join(args, " "), err, stdout.String(), stderr.String())
Joe Tsai707894e2019-03-01 12:50:52 -0800434 }
435 return stdout.String()
436}
Damien Neila80229e2019-06-20 12:53:48 -0700437
Joe Tsai7164af52019-08-07 19:27:43 -0700438func mustRunCommand(t *testing.T, args ...string) string {
439 t.Helper()
440 return command{}.mustRun(t, args...)
441}
442
Damien Neila80229e2019-06-20 12:53:48 -0700443var benchmarkProtos = []string{
444 "benchmarks/benchmarks.proto",
445 "benchmarks/datasets/google_message1/proto2/benchmark_message1_proto2.proto",
446 "benchmarks/datasets/google_message1/proto3/benchmark_message1_proto3.proto",
447 "benchmarks/datasets/google_message2/benchmark_message2.proto",
448 "benchmarks/datasets/google_message3/benchmark_message3.proto",
449 "benchmarks/datasets/google_message3/benchmark_message3_1.proto",
450 "benchmarks/datasets/google_message3/benchmark_message3_2.proto",
451 "benchmarks/datasets/google_message3/benchmark_message3_3.proto",
452 "benchmarks/datasets/google_message3/benchmark_message3_4.proto",
453 "benchmarks/datasets/google_message3/benchmark_message3_5.proto",
454 "benchmarks/datasets/google_message3/benchmark_message3_6.proto",
455 "benchmarks/datasets/google_message3/benchmark_message3_7.proto",
456 "benchmarks/datasets/google_message3/benchmark_message3_8.proto",
457 "benchmarks/datasets/google_message4/benchmark_message4.proto",
458 "benchmarks/datasets/google_message4/benchmark_message4_1.proto",
459 "benchmarks/datasets/google_message4/benchmark_message4_2.proto",
460 "benchmarks/datasets/google_message4/benchmark_message4_3.proto",
461}