[build_init] Ensure the input build is valid

Change-Id: Iffdf4fef330f87aa2e11709bdcd4dab19db1b584
diff --git a/cmd/build_init/main.go b/cmd/build_init/main.go
index c3abd31..decb6d8 100644
--- a/cmd/build_init/main.go
+++ b/cmd/build_init/main.go
@@ -96,9 +96,32 @@
 	if err != nil {
 		return fmt.Errorf("failed to read build.proto: %v", err)
 	}
+	if err := validateBuild(*build); err != nil {
+		return fmt.Errorf("invalid build message: %v", err)
+	}
 	return err
 }
 
+func validateBuild(build buildbucketpb.Build) error {
+	if build.Input == nil {
+		return errors.New("build has no input")
+	}
+	if build.Input.GitilesCommit == nil {
+		return errors.New("build input has no Gitiles commit")
+	}
+	if build.Builder == nil {
+		return errors.New("input build has no builder information")
+	}
+	if build.Builder.Bucket == "" {
+		return errors.New("input build's builder has no bucket")
+	}
+	if build.Builder.Builder == "" {
+		return errors.New("input build's builder name is empty")
+	}
+	return nil
+}
+
+// Execute runs the program. Public for testing.
 func execute(ctx context.Context) (code int) {
 	if err := checkout.Checkout(*build.Input, *specRepoURL); err != nil {
 		log.Printf("failed to checkout %s: %v", specRepoURL.String(), err)
diff --git a/cmd/build_init/main_test.go b/cmd/build_init/main_test.go
index 537fe11..111b8e7 100644
--- a/cmd/build_init/main_test.go
+++ b/cmd/build_init/main_test.go
@@ -71,3 +71,125 @@
 		t.Errorf("expected an error but got %v", output)
 	}
 }
+
+func TestValidateBuild(t *testing.T) {
+	tests := []struct {
+		name        string
+		build       *buildbucketpb.Build
+		expectError bool
+	}{
+		{
+			name: "should err if builder property is nil",
+			build: &buildbucketpb.Build{
+				Input: &buildbucketpb.Build_Input{
+					GitilesCommit: &buildbucketpb.GitilesCommit{
+						Host:    "host",
+						Project: "project",
+						Id:      "id",
+					},
+				},
+			},
+			expectError: true,
+		},
+		{
+			name: "should err if builder bucket is empty",
+			build: &buildbucketpb.Build{
+				Builder: &buildbucketpb.BuilderID{
+					Project: "project",
+					Builder: "builder",
+				},
+				Input: &buildbucketpb.Build_Input{
+					GitilesCommit: &buildbucketpb.GitilesCommit{
+						Host:    "host",
+						Project: "project",
+						Id:      "id",
+					},
+				},
+			},
+			expectError: true,
+		},
+		{
+			name: "should err if builder name is empty",
+			build: &buildbucketpb.Build{
+				Builder: &buildbucketpb.BuilderID{
+					Project: "project",
+					Bucket:  "bucket",
+				},
+				Input: &buildbucketpb.Build_Input{
+					GitilesCommit: &buildbucketpb.GitilesCommit{
+						Host:    "host",
+						Project: "project",
+						Id:      "id",
+					},
+				},
+			},
+			expectError: true,
+		},
+		{
+			name: "should err if the build input is nil",
+			build: &buildbucketpb.Build{
+				Builder: &buildbucketpb.BuilderID{
+					Project: "project",
+					Builder: "builder",
+					Bucket:  "bucket",
+				},
+			},
+			expectError: true,
+		},
+		{
+			name: "should err if the build input has no GitilesCommit",
+			build: &buildbucketpb.Build{
+				Builder: &buildbucketpb.BuilderID{
+					Project: "project",
+					Builder: "builder",
+					Bucket:  "bucket",
+				},
+				Input: &buildbucketpb.Build_Input{},
+			},
+			expectError: true,
+		},
+		{
+			name: "should err if the build input has a GerritChange but no GitilesCommit",
+			build: &buildbucketpb.Build{
+				Builder: &buildbucketpb.BuilderID{
+					Project: "project",
+					Builder: "builder",
+					Bucket:  "bucket",
+				},
+				Input: &buildbucketpb.Build_Input{
+					GerritChanges: []*buildbucketpb.GerritChange{{}},
+				},
+			},
+			expectError: true,
+		},
+		{
+			name: "should return nil if all fields are non-nil and non-empty",
+			build: &buildbucketpb.Build{
+				Builder: &buildbucketpb.BuilderID{
+					Project: "project",
+					Bucket:  "bucket",
+					Builder: "builder",
+				},
+				Input: &buildbucketpb.Build_Input{
+					GitilesCommit: &buildbucketpb.GitilesCommit{
+						Host:    "host",
+						Project: "project",
+						Id:      "id",
+					},
+				},
+			},
+			expectError: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			err := validateBuild(*tt.build)
+			switch {
+			case err != nil && !tt.expectError:
+				t.Errorf("unexpected error: %v", err)
+			case err == nil && tt.expectError:
+				t.Errorf("wanted error but got nil")
+			}
+		})
+	}
+}