tast: Add empty implementation of log reporting server.

This change adds a new file with an empty implemenation of Reports gRPC
server class and starts it in tast_rtd.

BUG=chromium:1166937
TEST=fast_build.sh -t chromiumos/tast/cmd/tast_rtd/internal/rpc

Change-Id: Iaa6eea0e99fe8625a00ff4b572de64aacc8d6333
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/tast/+/2631783
Reviewed-by: Seewai Fu <seewaifu@google.com>
Tested-by: Tatsuhisa Yamaguchi <yamaguchi@chromium.org>
Commit-Queue: Tatsuhisa Yamaguchi <yamaguchi@chromium.org>
diff --git a/src/chromiumos/tast/cmd/tast_rtd/internal/rpc/reports.go b/src/chromiumos/tast/cmd/tast_rtd/internal/rpc/reports.go
new file mode 100644
index 0000000..2e1d5eb
--- /dev/null
+++ b/src/chromiumos/tast/cmd/tast_rtd/internal/rpc/reports.go
@@ -0,0 +1,58 @@
+// Copyright 2021 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Package rpc provides the RPC services by tast_rtd
+package rpc
+
+import (
+	"context"
+	"fmt"
+	"net"
+
+	"github.com/golang/protobuf/ptypes/empty"
+	"google.golang.org/grpc"
+
+	"chromiumos/tast/internal/protocol"
+)
+
+// reportsServer implements the tast.internal.protocol.ReportsServer.
+type reportsServer struct {
+	srv      *grpc.Server
+	listener net.Listener
+}
+
+var _ protocol.ReportsServer = (*reportsServer)(nil)
+
+func (s reportsServer) LogStream(protocol.Reports_LogStreamServer) error {
+	return nil
+}
+
+func (s reportsServer) ReportResult(ctx context.Context, req *protocol.ReportResultRequest) (*empty.Empty, error) {
+	return nil, nil
+}
+
+func (s reportsServer) Stop() {
+	s.srv.Stop()
+	s.listener.Close()
+}
+
+func (s reportsServer) Address() string {
+	return s.listener.Addr().String()
+}
+
+// NewReportsServer starts a Reports gRPC service and returns a reportsServer object when success.
+// The caller is responsible for calling Stop() method.
+func NewReportsServer(port int) (*reportsServer, error) {
+	l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
+	if err != nil {
+		return nil, err
+	}
+	s := reportsServer{
+		srv:      grpc.NewServer(),
+		listener: l,
+	}
+	protocol.RegisterReportsServer(s.srv, &s)
+	go s.srv.Serve(l)
+	return &s, nil
+}
diff --git a/src/chromiumos/tast/cmd/tast_rtd/internal/rpc/reports_test.go b/src/chromiumos/tast/cmd/tast_rtd/internal/rpc/reports_test.go
new file mode 100644
index 0000000..680471b
--- /dev/null
+++ b/src/chromiumos/tast/cmd/tast_rtd/internal/rpc/reports_test.go
@@ -0,0 +1,34 @@
+// Copyright 2021 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package rpc
+
+import (
+	"context"
+	"testing"
+
+	"google.golang.org/grpc"
+
+	"chromiumos/tast/internal/protocol"
+)
+
+func TestReportsServer_LogStream(t *testing.T) {
+	srv, err := NewReportsServer(0)
+	if err != nil {
+		t.Fatalf("Failed to start Reports server: %v", err)
+	}
+	addr := srv.Address()
+	conn, err := grpc.Dial(addr, grpc.WithInsecure())
+	if err != nil {
+		t.Fatalf("Failed to dial: %v", err)
+	}
+	defer conn.Close()
+
+	// Test that the server is started and reachable by calling a method.
+	// TODO(crbug.com/1166942): Test with actual usage of LogStream.
+	cl := protocol.NewReportsClient(conn)
+	if _, err := cl.LogStream(context.Background()); err != nil {
+		t.Fatalf("Failed at LogStream: %v", err)
+	}
+}
diff --git a/src/chromiumos/tast/cmd/tast_rtd/main.go b/src/chromiumos/tast/cmd/tast_rtd/main.go
index 56af23a..ec9186a 100644
--- a/src/chromiumos/tast/cmd/tast_rtd/main.go
+++ b/src/chromiumos/tast/cmd/tast_rtd/main.go
@@ -18,6 +18,8 @@
 
 	rtd "go.chromium.org/chromiumos/config/go/api/test/rtd/v1"
 	"google.golang.org/grpc"
+
+	"chromiumos/tast/cmd/tast_rtd/internal/rpc"
 )
 
 // Version is the version info of this command. It is filled in during emerge.
@@ -67,6 +69,7 @@
 		version := flag.Bool("version", false, "print version and exit")
 		input := flag.String("input", "", "specify the test invocation request protobuf input file")
 		rtdPath := flag.String("rtd", "/usr/src/rtd", "specify the root directory of rtd files and executables.")
+		serverPort := flag.Int("reports_port", 0, "specify the port number to start Reports server.")
 		flag.Parse()
 
 		if *version {
@@ -74,6 +77,12 @@
 			return 0
 		}
 
+		srv, err := rpc.NewReportsServer(*serverPort)
+		if err != nil {
+			log.Fatalf("Failed to start Reports server: %v", err)
+		}
+		defer srv.Stop()
+
 		logFile, err := createLogFile()
 		if err != nil {
 			log.Fatalf("Failed to create log file: %v", err)