blob: 8c2d956e8f22163b36e4bc7f58335e6eb02d25bb [file] [log] [blame]
// Copyright 2018 The Fuchsia 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 fxctx_test
import (
"context"
"fmt"
"reflect"
"testing"
"fuchsia.googlesource.com/infra/infra/fxctx"
)
const TestKey = fxctx.ContextKey("test-key")
// A testCase for Get(). InputValue is the value to store in the context. The encoded
// value is decoded from the Context into OutputValue. ExpectOK indicates whether Get
// should return true (the value is present in the Context). ExpectError indicates whether
// Get should return an error.
type getTestCase struct {
InputValue interface{}
OutputValue interface{}
ExpectError bool
}
func TestGet(t *testing.T) {
testGet := func(t *testing.T, testCase getTestCase) {
ctx := context.Background()
if testCase.InputValue != nil {
var err error
ctx, err = fxctx.Set(ctx, TestKey, testCase.InputValue)
if err != nil {
t.Fatal(err)
}
}
err := fxctx.Get(ctx, TestKey, testCase.OutputValue)
if testCase.ExpectError != (err != nil) {
expectation := "did not expect error"
reality := fmt.Sprintf("got error: %v", err)
if testCase.ExpectError {
expectation = "expected error"
reality = "got nil"
}
t.Errorf("%s but %s", expectation, reality)
}
}
t.Run("should error if the key is not present", func(t *testing.T) {
// Pass nil as InputValue to simulate a missing key.
testGet(t, getTestCase{
InputValue: nil,
OutputValue: new(string),
ExpectError: true,
})
})
t.Run("should return true and error if the value cannot be decoded", func(t *testing.T) {
// A map cannot be decoded into a string.
testGet(t, getTestCase{
InputValue: map[string]string{"foo": "hi"},
OutputValue: new(string),
ExpectError: true,
})
})
t.Run("should return true and decode a value", func(t *testing.T) {
testGet(t, getTestCase{
InputValue: "hello world!",
OutputValue: new(string),
ExpectError: false,
})
})
}
// A test case for Set(). Key and Value are the key-value pair to set in the Context.
// ExpectedContext is the expected output Context. ExpectError indicates whether Set
// should return an error.
type setTestCase struct {
Key fxctx.ContextKey
Value interface{}
ExpectedContext context.Context
ExpectError bool
}
func TestSet(t *testing.T) {
testSet := func(t *testing.T, testCase setTestCase) {
ctx, err := fxctx.Set(context.Background(), testCase.Key, testCase.Value)
if testCase.ExpectError != (err != nil) {
expectation := "did not expect error"
reality := fmt.Sprintf("got error: %v", err)
if testCase.ExpectError {
expectation = "expected error"
reality = "got nil"
}
t.Errorf("%s but %s", expectation, reality)
}
if !reflect.DeepEqual(ctx, testCase.ExpectedContext) {
t.Errorf("Invalid context\nExpected %+v\nGot %+v",
testCase.ExpectedContext, ctx)
}
}
t.Run("should fail if the value cannot be encoded", func(t *testing.T) {
// Channels cannot be encoded as JSON.
channel := make(chan int)
defer close(channel)
testSet(t, setTestCase{
Value: channel,
Key: TestKey,
ExpectedContext: nil,
ExpectError: true,
})
// Functions cannot be encoded as JSON.
aFunction := func() {}
testSet(t, setTestCase{
Value: aFunction,
Key: TestKey,
ExpectedContext: nil,
ExpectError: true,
})
})
t.Run("should return a context with the value marshaled as JSON", func(t *testing.T) {
testSet(t, setTestCase{
Value: "Hello, World!",
Key: TestKey,
ExpectedContext: context.WithValue(
context.Background(),
TestKey,
[]byte("\"Hello, World!\"")),
ExpectError: false,
})
})
}