Add unit test for EventHandler

Test: the added file
Bug: NA
Change-Id: Id50105e84585348ce8540f52407224daeb8eb0d4
diff --git a/metrics/Android.bp b/metrics/Android.bp
index 3668668..1e3a6f0 100644
--- a/metrics/Android.bp
+++ b/metrics/Android.bp
@@ -24,4 +24,7 @@
     srcs: [
         "event_handler.go",
     ],
+    testSrcs: [
+        "event_handler_test.go",
+    ],
 }
diff --git a/metrics/event_handler.go b/metrics/event_handler.go
index 3fd0f37..35a6858 100644
--- a/metrics/event_handler.go
+++ b/metrics/event_handler.go
@@ -56,6 +56,9 @@
 // call to End (though other events may begin and end before this event ends).
 // Events within the same scope must have unique names.
 func (h *EventHandler) Begin(name string) {
+	if strings.ContainsRune(name, '.') {
+		panic(fmt.Sprintf("illegal event name (avoid dot): %s", name))
+	}
 	h.scopeIds = append(h.scopeIds, name)
 	h.scopeStartTimes = append(h.scopeStartTimes, _now())
 }
@@ -71,7 +74,7 @@
 // themselves been marked completed.
 func (h *EventHandler) End(name string) {
 	if len(h.scopeIds) == 0 || name != h.scopeIds[len(h.scopeIds)-1] {
-		panic(fmt.Errorf("Unexpected scope end '%s'. Current scope: (%s)",
+		panic(fmt.Errorf("unexpected scope end '%s'. Current scope: (%s)",
 			name, h.scopeIds))
 	}
 	event := Event{
@@ -94,14 +97,14 @@
 func (h *EventHandler) CompletedEvents() []Event {
 	if len(h.scopeIds) > 0 {
 		panic(fmt.Errorf(
-			"Retrieving events before all events have been closed. Current scope: (%s)",
+			"retrieving events before all events have been closed. Current scope: (%s)",
 			h.scopeIds))
 	}
 	// Validate no two events have the same full id.
 	ids := map[string]struct{}{}
 	for _, event := range h.completedEvents {
 		if _, containsId := ids[event.Id]; containsId {
-			panic(fmt.Errorf("Duplicate event registered: %s", event.Id))
+			panic(fmt.Errorf("duplicate event registered: %s", event.Id))
 		}
 		ids[event.Id] = struct{}{}
 	}
diff --git a/metrics/event_handler_test.go b/metrics/event_handler_test.go
new file mode 100644
index 0000000..08a59bd
--- /dev/null
+++ b/metrics/event_handler_test.go
@@ -0,0 +1,100 @@
+// Copyright 2022 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package metrics
+
+import (
+	"fmt"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+func Map[A any, B any](in []A, f func(A) B) []B {
+	r := make([]B, len(in))
+	for i, a := range in {
+		r[i] = f(a)
+	}
+	return r
+}
+
+func TestEventNameWithDot(t *testing.T) {
+	defer func() {
+		r := fmt.Sprintf("%v", recover())
+		if !strings.HasPrefix(r, "illegal event name") {
+			t.Errorf("The code did not panic in the expected manner: %s", r)
+		}
+	}()
+	eh := EventHandler{}
+	eh.Begin("a.")
+}
+
+func TestEventNesting(t *testing.T) {
+	eh := EventHandler{}
+	eh.Begin("a")
+	eh.Begin("b")
+	eh.End("b")
+	eh.Begin("c")
+	eh.End("c")
+	eh.End("a")
+	expected := []string{"a.b", "a.c", "a"}
+	actual := Map(eh.CompletedEvents(), func(e Event) string {
+		return e.Id
+	})
+	if !reflect.DeepEqual(expected, actual) {
+		t.Errorf("expected: %s actual %s", expected, actual)
+	}
+}
+
+func TestEventOverlap(t *testing.T) {
+	defer func() {
+		r := fmt.Sprintf("%v", recover())
+		if !strings.Contains(r, "unexpected scope end 'a'") {
+			t.Errorf("expected panic but: %s", r)
+		}
+	}()
+	eh := EventHandler{}
+	eh.Begin("a")
+	eh.Begin("b")
+	eh.End("a")
+}
+
+func TestEventDuplication(t *testing.T) {
+	eh := EventHandler{}
+	eh.Begin("a")
+	eh.Begin("b")
+	eh.End("b")
+	eh.Begin("b")
+	eh.End("b")
+	eh.End("a")
+	defer func() {
+		r := fmt.Sprintf("%v", recover())
+		if !strings.HasPrefix(r, "duplicate event") {
+			t.Errorf("expected panic but: %s", r)
+		}
+	}()
+	eh.CompletedEvents()
+}
+
+func TestIncompleteEvent(t *testing.T) {
+	eh := EventHandler{}
+	eh.Begin("a")
+	defer func() {
+		r := fmt.Sprintf("%v", recover())
+		if !strings.HasPrefix(r, "retrieving events before all events have been closed.") {
+			t.Errorf("expected panic but: %s", r)
+		}
+	}()
+	eh.CompletedEvents()
+}