Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce tflogtest and tfsdklogtest packages #62

Merged
merged 2 commits into from May 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changelog/62.txt
@@ -0,0 +1,7 @@
```release-note:feature
Added `tflogtest` package, which provides functionality for unit testing of provider logging
```

```release-note:feature
Added `tfsdklogtest` package, which provides functionality for unit testing of SDK logging
```
3 changes: 2 additions & 1 deletion internal/loggertest/json_decode.go
Expand Up @@ -8,11 +8,12 @@ import (

func MultilineJSONDecode(data io.Reader) ([]map[string]interface{}, error) {
var result []map[string]interface{}
var entry map[string]interface{}

dec := json.NewDecoder(data)

for {
var entry map[string]interface{}

err := dec.Decode(&entry)

if err == io.EOF {
Expand Down
3 changes: 3 additions & 0 deletions tflogtest/doc.go
@@ -0,0 +1,3 @@
// Package tflogtest provides functionality for unit testing of provider
// logging.
package tflogtest
13 changes: 13 additions & 0 deletions tflogtest/json_decode.go
@@ -0,0 +1,13 @@
package tflogtest

import (
"io"

"github.com/hashicorp/terraform-plugin-log/internal/loggertest"
)

// MultilineJSONDecode supports decoding the output of a JSON logger into a
// slice of maps, with each element representing a log entry.
func MultilineJSONDecode(data io.Reader) ([]map[string]interface{}, error) {
return loggertest.MultilineJSONDecode(data)
}
38 changes: 38 additions & 0 deletions tflogtest/json_decode_example_test.go
@@ -0,0 +1,38 @@
package tflogtest

import (
"bytes"
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-log/tflog"
)

func ExampleMultilineJSONDecode() {
var output bytes.Buffer

ctx := RootLogger(context.Background(), &output)

// Root provider logger is now available for usage, such as writing
// entries, calling With(), or calling NewSubsystem().
tflog.Trace(ctx, "entry 1")
tflog.Trace(ctx, "entry 2")

entries, err := MultilineJSONDecode(&output)

if err != nil {
// Typical unit testing would call t.Fatalf() here.
fmt.Printf("unable to read multiple line JSON: %s", err)
}

// Entries can be checked via go-cmp's cmp.Diff() or other testing methods.
// This example outputs them to stdout in an explicitly formatted string,
// which would not be expected in typical unit testing.
for _, entry := range entries {
fmt.Printf("@message: %s\n", entry["@message"])
}

// Output:
// @message: entry 1
// @message: entry 2
}
21 changes: 21 additions & 0 deletions tflogtest/root_logger.go
@@ -0,0 +1,21 @@
package tflogtest

import (
"context"
"io"

"github.com/hashicorp/terraform-plugin-log/internal/loggertest"
)

// RootLogger returns a context containing a provider root logger suitable for
// unit testing that is:
//
// - Written to the given io.Writer, such as a bytes.Buffer.
// - Written with JSON output, that can be decoded with MultilineJSONDecode.
// - Log level set to TRACE.
// - Without location/caller information in log entries.
// - Without timestamps in log entries.
//
func RootLogger(ctx context.Context, output io.Writer) context.Context {
return loggertest.ProviderRoot(ctx, output)
}
27 changes: 27 additions & 0 deletions tflogtest/root_logger_example_test.go
@@ -0,0 +1,27 @@
package tflogtest

import (
"bytes"
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-log/tflog"
)

func ExampleRootLogger() {
var output bytes.Buffer

ctx := RootLogger(context.Background(), &output)

// Root provider logger is now available for usage, such as writing
// entries, calling With(), or calling NewSubsystem().
tflog.Trace(ctx, "hello, world", map[string]interface{}{
"foo": 123,
"colors": []string{"red", "blue", "green"},
})

fmt.Println(output.String())

// Output:
// {"@level":"trace","@message":"hello, world","@module":"provider","colors":["red","blue","green"],"foo":123}
}
3 changes: 3 additions & 0 deletions tfsdklogtest/doc.go
@@ -0,0 +1,3 @@
// Package tfsdklogtest provides functionality for unit testing of SDK
// logging. Provider developers should use the tflogtest package.
package tfsdklogtest
13 changes: 13 additions & 0 deletions tfsdklogtest/json_decode.go
@@ -0,0 +1,13 @@
package tfsdklogtest

import (
"io"

"github.com/hashicorp/terraform-plugin-log/internal/loggertest"
)

// MultilineJSONDecode supports decoding the output of a JSON logger into a
// slice of maps, with each element representing a log entry.
func MultilineJSONDecode(data io.Reader) ([]map[string]interface{}, error) {
return loggertest.MultilineJSONDecode(data)
}
38 changes: 38 additions & 0 deletions tfsdklogtest/json_decode_example_test.go
@@ -0,0 +1,38 @@
package tfsdklogtest

import (
"bytes"
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-log/tfsdklog"
)

func ExampleMultilineJSONDecode() {
var output bytes.Buffer

ctx := RootLogger(context.Background(), &output)

// Root SDK logger is now available for usage, such as writing entries,
// calling With(), or calling NewSubsystem().
tfsdklog.Trace(ctx, "entry 1")
tfsdklog.Trace(ctx, "entry 2")

entries, err := MultilineJSONDecode(&output)

if err != nil {
// Typical unit testing would call t.Fatalf() here.
fmt.Printf("unable to read multiple line JSON: %s", err)
}

// Entries can be checked via go-cmp's cmp.Diff() or other testing methods.
// This example outputs them to stdout in an explicitly formatted string,
// which would not be expected in typical unit testing.
for _, entry := range entries {
fmt.Printf("@message: %s\n", entry["@message"])
}

// Output:
// @message: entry 1
// @message: entry 2
}
21 changes: 21 additions & 0 deletions tfsdklogtest/root_logger.go
@@ -0,0 +1,21 @@
package tfsdklogtest

import (
"context"
"io"

"github.com/hashicorp/terraform-plugin-log/internal/loggertest"
)

// RootLogger returns a context containing a SDK root logger suitable for unit
// testing that is:
//
// - Written to the given io.Writer, such as a bytes.Buffer.
// - Written with JSON output, that can be decoded with MultilineJSONDecode.
// - Log level set to TRACE.
// - Without location/caller information in log entries.
// - Without timestamps in log entries.
//
func RootLogger(ctx context.Context, output io.Writer) context.Context {
return loggertest.SDKRoot(ctx, output)
}
27 changes: 27 additions & 0 deletions tfsdklogtest/root_logger_example_test.go
@@ -0,0 +1,27 @@
package tfsdklogtest

import (
"bytes"
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-log/tfsdklog"
)

func ExampleRootLogger() {
var output bytes.Buffer

ctx := RootLogger(context.Background(), &output)

// Root SDK logger is now available for usage, such as writing entries,
// calling With(), or calling NewSubsystem().
tfsdklog.Trace(ctx, "hello, world", map[string]interface{}{
"foo": 123,
"colors": []string{"red", "blue", "green"},
})

fmt.Println(output.String())

// Output:
// {"@level":"trace","@message":"hello, world","@module":"sdk","colors":["red","blue","green"],"foo":123}
}