[testrunner] Record duration_milliseconds in summary.json

This brings parity with the on-Fuchsia runtests code. Having this data
in structured form will be useful for finding opportunities for
optimization.

Bug: IN-1715
Change-Id: Ie40de9fd0c3f726ca2a41f093e54c2b3797b16cf
diff --git a/cmd/testrunner/outputs/summary.go b/cmd/testrunner/outputs/summary.go
index 3ba3194..3b24c98 100644
--- a/cmd/testrunner/outputs/summary.go
+++ b/cmd/testrunner/outputs/summary.go
@@ -24,9 +24,10 @@
 	// pathInArchive gives a valid relative path.
 	pathInArchive = strings.TrimLeft(pathInArchive, "//")
 	o.Summary.Tests = append(o.Summary.Tests, runtests.TestDetails{
-		Name:       result.Name,
-		OutputFile: pathInArchive,
-		Result:     result.Result,
+		Name:           result.Name,
+		OutputFile:     pathInArchive,
+		Result:         result.Result,
+		DurationMillis: result.EndTime.Sub(result.StartTime).Nanoseconds() / 1000 / 1000,
 	})
 }
 
diff --git a/cmd/testrunner/outputs/summary_test.go b/cmd/testrunner/outputs/summary_test.go
index f3c6ed3..7354d77 100644
--- a/cmd/testrunner/outputs/summary_test.go
+++ b/cmd/testrunner/outputs/summary_test.go
@@ -7,6 +7,7 @@
 import (
 	"reflect"
 	"testing"
+	"time"
 
 	"go.fuchsia.dev/tools/cmd/testrunner/outputs"
 	"go.fuchsia.dev/tools/runtests"
@@ -14,9 +15,12 @@
 )
 
 func TestSummaryOutput(t *testing.T) {
+	start := time.Now()
 	inputs := []testrunner.TestResult{{
-		Name:   "test_a",
-		Result: runtests.TestFailure,
+		Name:      "test_a",
+		Result:    runtests.TestFailure,
+		StartTime: start,
+		EndTime:   start.Add(10 * time.Millisecond),
 	}, {
 		Name:   "test_b",
 		Result: runtests.TestSuccess,
@@ -29,13 +33,16 @@
 
 	expectedSummary := runtests.TestSummary{
 		Tests: []runtests.TestDetails{{
-			Name:       "test_a",
-			OutputFile: "test_a/stdout-and-stderr.txt",
-			Result:     runtests.TestFailure,
+			Name:           "test_a",
+			OutputFile:     "test_a/stdout-and-stderr.txt",
+			Result:         runtests.TestFailure,
+			DurationMillis: 10,
 		}, {
 			Name:       "test_b",
 			OutputFile: "test_b/stdout-and-stderr.txt",
 			Result:     runtests.TestSuccess,
+			// Unspecified start and end times == 0
+			DurationMillis: 0,
 		}},
 	}
 
diff --git a/runtests/runtests.go b/runtests/runtests.go
index 4b38602..00e82cc 100644
--- a/runtests/runtests.go
+++ b/runtests/runtests.go
@@ -55,4 +55,7 @@
 
 	// DataSinks gives the data sinks attached to a test.
 	DataSinks map[string][]DataSink `json:"data_sinks,omitempty"`
+
+	// Duration is how long the test execution took.
+	DurationMillis int64 `json:"duration_milliseconds"`
 }