[tilo] Store actions and ResultStore host in Context

IN-699 #comment

Change-Id: If0d241414b82c1b6fb95ca539ba30f136b4f2066
diff --git a/tilo/resultstore/context.go b/tilo/resultstore/context.go
index 0f68455..6f7c491 100644
--- a/tilo/resultstore/context.go
+++ b/tilo/resultstore/context.go
@@ -31,6 +31,12 @@
 // Please do not add information to this interface unless it is necessary to support
 // creating Invocations in a distributed manner.
 type Context interface {
+	// SetResultStoreHost stores the hostname of the ResultStore backend.
+	SetResultStoreHost(string) bool
+
+	// ResultStoreHost is the hostname of the ResultStore backend.
+	ResultStoreHost() string
+
 	// SetAuthToken stores the Invocation's auth token.
 	SetAuthToken(string) bool
 
@@ -60,6 +66,12 @@
 
 	// ConfiguredTarget returns a ConfiguredTarget's name, given its ID.
 	ConfiguredTarget(targetID, configID string) string
+
+	// SetTestAction stores a TestAction's name under its ID.
+	SetTestAction(id, name string) bool
+
+	// TestAction returns a TestAction's name, given its ID.
+	TestAction(id string) string
 }
 
 // NewContext returns a new Context.
@@ -69,11 +81,25 @@
 
 // The default Context implementation.
 type rsContext struct {
+	ResultStoreHostValue  string            `json:"resultstore_host"`
 	AuthTokenValue        string            `json:"auth_token"`
 	InvocationNameValue   string            `json:"invocation_name"`
 	InvocationIDValue     string            `json:"invocation_id"`
 	TargetNames           map[string]string `json:"targets"`
 	ConfiguredTargetNames map[string]string `json:"configured_targets"`
+	TestActionNames       map[string]string `json:"test_actions"`
+}
+
+func (c *rsContext) SetResultStoreHost(value string) bool {
+	if c.ResultStoreHostValue != "" && c.ResultStoreHostValue != value {
+		return false
+	}
+	c.ResultStoreHostValue = value
+	return true
+}
+
+func (c *rsContext) ResultStoreHost() string {
+	return c.ResultStoreHostValue
 }
 
 func (c *rsContext) SetAuthToken(value string) bool {
@@ -136,15 +162,32 @@
 		return false
 	}
 
-	ID := c.createConfiguredTargetID(targetID, configID)
-	c.ConfiguredTargetNames[ID] = name
+	id := c.createConfiguredTargetID(targetID, configID)
+	c.ConfiguredTargetNames[id] = name
 	return true
 }
 
 func (c *rsContext) ConfiguredTarget(targetID, configID string) string {
 	c.ensureConfiguredTargets()
-	ID := c.createConfiguredTargetID(targetID, configID)
-	val, _ := c.ConfiguredTargetNames[ID]
+	id := c.createConfiguredTargetID(targetID, configID)
+	val, _ := c.ConfiguredTargetNames[id]
+	return val
+}
+
+func (c *rsContext) SetTestAction(id, name string) bool {
+	c.ensureTestActions()
+	oldName := c.TestAction(id)
+	if oldName != "" && oldName != name {
+		return false
+	}
+
+	c.TestActionNames[id] = name
+	return true
+}
+
+func (c *rsContext) TestAction(id string) string {
+	c.ensureTestActions()
+	val, _ := c.TestActionNames[id]
 	return val
 }
 
@@ -160,6 +203,12 @@
 	}
 }
 
+func (c *rsContext) ensureTestActions() {
+	if c.TestActionNames == nil {
+		c.TestActionNames = make(map[string]string)
+	}
+}
+
 func (c rsContext) createConfiguredTargetID(targetID, configID string) string {
 	return fmt.Sprintf("(target=%s,config=%s)", targetID, configID)
 }
diff --git a/tilo/resultstore/context_test.go b/tilo/resultstore/context_test.go
index e679039..9ff725b 100644
--- a/tilo/resultstore/context_test.go
+++ b/tilo/resultstore/context_test.go
@@ -39,6 +39,33 @@
 		})
 	})
 
+	t.Run("SetResultStoreHost", func(t *testing.T) {
+		t.Run("should store the ResultStore host", func(t *testing.T) {
+			ctx, fxt := setup(t)
+			fxt.Assert(ctx.SetResultStoreHost("hostname"), "unable to set ResultStore host")
+		})
+		t.Run("should error if overwriting the ResultStore host", func(t *testing.T) {
+			ctx, fxt := setup(t)
+			fxt.Assert(ctx.SetResultStoreHost("hostname"), "unable to set ResultStore host")
+			// Same value should not error
+			fxt.Assert(ctx.SetResultStoreHost("hostname"), "unable to set ResultStore host")
+			fxt.Assert(!ctx.SetResultStoreHost("new_hostname"), "should not have been able to overwrite ResultStore host")
+		})
+	})
+
+	t.Run("ResultStoreHost", func(t *testing.T) {
+		t.Run("should return the ResultStore host", func(t *testing.T) {
+			ctx, fxt := setup(t)
+
+			// Should start off empty.
+			hostname := ctx.ResultStoreHost()
+			fxt.Assert(hostname == "", "hostname should be empty. Got %s", hostname)
+			fxt.Assert(ctx.SetResultStoreHost("hostname"), "unable to set ResultStore host")
+			hostname = ctx.ResultStoreHost()
+			fxt.Assert(hostname == "hostname", "got unexpected value for hostname: %s", hostname)
+		})
+	})
+
 	t.Run("SetInvocationName", func(t *testing.T) {
 		t.Run("should store the Invocation name", func(t *testing.T) {
 			ctx, fxt := setup(t)
@@ -53,6 +80,19 @@
 		})
 	})
 
+	t.Run("InvocationName", func(t *testing.T) {
+		t.Run("should return the Invocation name", func(t *testing.T) {
+			ctx, fxt := setup(t)
+
+			// Should start off empty.
+			invocation := ctx.InvocationName()
+			fxt.Assert(invocation == "", "Invocation should be empty. Got %s", invocation)
+			fxt.Assert(ctx.SetInvocationName("inv_name"), "unable to set Invocation")
+			invocation = ctx.InvocationName()
+			fxt.Assert(invocation == "inv_name", "got unexpected value for Invocation name: %s", invocation)
+		})
+	})
+
 	t.Run("SetInvocationID", func(t *testing.T) {
 		t.Run("should store the Invocation ID", func(t *testing.T) {
 			ctx, fxt := setup(t)
@@ -156,6 +196,35 @@
 		})
 	})
 
+	t.Run("SetTestAction", func(t *testing.T) {
+		t.Run("should store the TestAction name", func(t *testing.T) {
+			ctx, fxt := setup(t)
+			fxt.Assert(ctx.SetTestAction("action_id", "action"), "unable to set action")
+		})
+		t.Run("should error if overwriting the TestAction name", func(t *testing.T) {
+			ctx, fxt := setup(t)
+			actionID := "action_id"
+			fxt.Assert(ctx.SetTestAction(actionID, "action"), "unable to set action")
+			// Same value should not error
+			fxt.Assert(ctx.SetTestAction(actionID, "action"), "unable to set action")
+			fxt.Assert(!ctx.SetTestAction(actionID, "new_action"), "should not have been able to overwrite the TestAction")
+		})
+	})
+
+	t.Run("TestAction", func(t *testing.T) {
+		t.Run("should return the TestAction", func(t *testing.T) {
+			ctx, fxt := setup(t)
+
+			// Should start off empty.
+			actionID := "action_id"
+			name := ctx.TestAction(actionID)
+			fxt.Assert(name == "", "TestAction should be empty. Got %s", name)
+			fxt.Assert(ctx.SetTestAction(actionID, "action_name"), "unable to set action")
+			name = ctx.TestAction("action_id")
+			fxt.Assert(name == "action_name", "got unexpected value for TestAction name: %s", name)
+		})
+	})
+
 	t.Run("should retain values after serialization", func(t *testing.T) {
 		ctx, fxt := setup(t)
 
@@ -165,6 +234,8 @@
 		fxt.Assert(ctx.SetInvocationID("inv_id"), "unable to set Invocatino ID")
 		fxt.Assert(ctx.SetTarget("target_id", "target"), "unable to set set Target")
 		fxt.Assert(ctx.SetConfiguredTarget("target_id", "config_id", "config_target"), "unable to set set ConfiguredTarget")
+		fxt.Assert(ctx.SetResultStoreHost("rs_host"), "unable to set ResultStore host")
+		fxt.Assert(ctx.SetTestAction("action_id", "action"), "unable to set TestAction")
 
 		// Marshal and unmarshal it.
 		bytes, err := json.Marshal(ctx)
@@ -188,5 +259,11 @@
 
 		ct := ctx.ConfiguredTarget("target_id", "config_id")
 		fxt.Assert(ct == "config_target", "expected 'config_target', got %s", ct)
+
+		action := ctx.TestAction("action_id")
+		fxt.Assert(action == "action", "expected 'action_id', got %s", action)
+
+		rsHost := ctx.ResultStoreHost()
+		fxt.Assert(rsHost == "rs_host", "expected 'rs_host', got %s", rsHost)
 	})
 }