| // 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, |
| }) |
| }) |
| } |