Calculate percentage of FW tests written

BUG=b:147815722
TEST=1. sudo emerge sys-firmware/fw-engprod-tools
     2. fw_e2e_coverage_summarizer

Change-Id: I78e9b4967d40755af6312afbdb47b03f9ca52234
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crostestutils/+/2041705
Tested-by: Greg Edelston <gredelston@google.com>
Reviewed-by: Kevin Shelton <kmshelton@chromium.org>
Commit-Queue: Greg Edelston <gredelston@google.com>
diff --git a/go/src/firmware/e2e_coverage_summarizer/fw_e2e_coverage_summarizer.go b/go/src/firmware/e2e_coverage_summarizer/fw_e2e_coverage_summarizer.go
index 8cab119..a3a7d6f 100644
--- a/go/src/firmware/e2e_coverage_summarizer/fw_e2e_coverage_summarizer.go
+++ b/go/src/firmware/e2e_coverage_summarizer/fw_e2e_coverage_summarizer.go
@@ -41,7 +41,7 @@
 // autotestDir is a filepath to the root directory of autotest.
 var autotestDir string
 
-// siteTestsDir is a filepath to autotestDir/server/site_tests/
+// siteTestsDir is a filepath to autotestDir/server/site_tests/.
 var siteTestsDir string
 
 // contains determines whether an array of strings contains a given string.
@@ -64,7 +64,7 @@
 
 // e2eTest.println displays the test struct's field names and values.
 func (t *e2eTest) println() {
-	fmt.Printf("%+v\n", *t)
+	log.Printf("%+v\n", *t)
 }
 
 // e2eTest.dir returns the test's folder within autotest/server/site_tests/
@@ -282,14 +282,44 @@
 	}
 }
 
-// Collect and report info on all firmware end-to-end tests.
+// Main collects and reports info on all firmware end-to-end tests.
 func main() {
+	// Collect written tests and unwritten/flaky test issues
 	existingTests, err := collectExistingE2ETests()
 	if err != nil {
-		log.Fatal(err)
+		log.Fatalf("collecting existing tests: %v", err)
 	}
-	for _, t := range existingTests {
-		t.println()
+	issues, err := IssuesList(UnwrittenFwTestReqParams)
+	if err != nil {
+		log.Fatalf("collecting unwritten tests: %v", err)
 	}
-	monorailDemo()
+
+	// Report on tests and issues
+	if len(existingTests) > 0 {
+		log.Print("### Existing end-to-end FW tests ###")
+		for _, t := range existingTests {
+			t.println()
+		}
+		log.Printf("Total: %d", len(existingTests))
+	} else {
+		log.Print("No end-to-end FW tests found.")
+	}
+	log.Print()
+	if len(issues) > 0 {
+		log.Print("### Unwritten/flaky FW tests ###")
+		for _, issue := range issues {
+			log.Print(issue)
+		}
+		log.Printf("Total: %d", len(issues))
+	} else {
+		log.Print("No unwritten FW tests found.")
+	}
+	log.Print()
+	log.Print("### TOTALS ###")
+	log.Printf("Existing e2e tests:          %d", len(existingTests))
+	log.Printf("Unwritten/flaky test issues: %d", len(issues))
+	if len(issues) > 0 {
+		p := float64(len(existingTests)) / float64((len(issues) + len(existingTests))) * 100
+		log.Printf("Proportion of tests written: %.2f%%", p)
+	}
 }
diff --git a/go/src/firmware/e2e_coverage_summarizer/monorail.go b/go/src/firmware/e2e_coverage_summarizer/monorail.go
index 18c66c4..3592be5 100644
--- a/go/src/firmware/e2e_coverage_summarizer/monorail.go
+++ b/go/src/firmware/e2e_coverage_summarizer/monorail.go
@@ -53,6 +53,12 @@
 	UpdatedMin        requestParam = "updatedMin"
 )
 
+// UnwrittenFwTestReqParams contains the canonical parameters to query Monorail for unwritten FW tests.
+var UnwrittenFwTestReqParams = map[requestParam]string{
+	Q:     "Component:OS>Firmware Component:Test>ChromeOS", // Space-separated means AND
+	Label: "Test-Missing,Test-Flaky,Test-Escape",           // Comma-separated means OR
+	Can:   "open"}                                          // Canned query filters down to open issues
+
 // User contains all the data about an author/cc/owner returned by the monorail.issues.list API.
 type User struct {
 	Kind          string
@@ -204,20 +210,3 @@
 	}
 	return issuesListResponse.Items, nil
 }
-
-// monorailDemo demonstrates how to get issues matching certain parameters.
-func monorailDemo() {
-	params := map[requestParam]string{
-		Q:     "Component:OS>Firmware Component:Test>ChromeOS", // Space-separated means AND
-		Label: "Test-Missing,Test-Flaky,Test-Escape",           // Comma-separated means OR
-		Can:   "open"}                                          // Canned query filters down to open issues
-	issues, err := IssuesList(params)
-	if err != nil {
-		log.Fatal(err)
-	}
-	for _, issue := range issues {
-		fmt.Printf("\nIssue %d: %s\nComponents:%s\nLabels:%s\n", issue.ID, issue.Title, issue.Components, issue.Labels)
-	}
-	fmt.Println()
-	log.Print("Total issues: ", len(issues))
-}