Merge pull request #49 from hashicorp/fix-ci-config

Fix CI config
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 488dae5..4918497 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,59 +1,164 @@
-version: 2.1
+version: 2.1
+
+orbs:
+  win: circleci/windows@2.2.0
 
 references:
-  images:
-    go: &GOLANG_IMAGE circleci/golang:latest
-  environments:
-    tmp: &TEST_RESULTS_PATH /tmp/test-results # path to where test results are saved
+  environment: &ENVIRONMENT
+    TEST_RESULTS_PATH: &TEST_RESULTS_PATH /tmp/test-results
+    WIN_TEST_RESULTS: &WIN_TEST_RESULTS c:\Users\circleci\AppData\Local\Temp\test-results
 
-# reusable 'executor' object for jobs
-executors:
-  go:
-    docker:
-      - image: *GOLANG_IMAGE
-    environment:
-      - TEST_RESULTS: *TEST_RESULTS_PATH
-
+commands:
+  run-gotests:
+    parameters:
+      cmd:
+        type: string
+      platform:
+        type: string
+    steps:
+      - run:
+          name: "Run go tests"
+          command: |
+            PACKAGE_NAMES=$(go list ./... | circleci tests split --split-by=timings --timings-type=classname)
+            echo "Running $(echo $PACKAGE_NAMES | wc -w) packages"
+            echo $PACKAGE_NAMES
+            << parameters.cmd >> --format=short-verbose --junitfile $TEST_RESULTS_PATH/go-multierror/gotestsum-report.xml -- -p 2 -cover -coverprofile=<< parameters.platform >>_cov_$CIRCLE_NODE_INDEX.part $PACKAGE_NAMES
+        
 jobs:
-  go-test:
-    executor: go
-    steps:
-      - checkout
-      - run: mkdir -p $TEST_RESULTS
+  linux-tests:
+    docker:
+      - image: docker.mirror.hashicorp.services/circleci/golang:<< parameters.go-version >>
+    parameters:
+      go-version:
+        type: string
+    environment: 
+      <<: *ENVIRONMENT
+    parallelism: 4
+    steps:
+      - run: go version
+      - checkout
+      - attach_workspace:
+          at: .
+      - run: mkdir -p $TEST_RESULTS_PATH/go-multierror
 
-      - restore_cache: # restore cache from dev-build job
-          keys:
-            - go-multierror-modcache-v1-{{ checksum "go.mod" }}
+      # Restore go module cache if there is one
+      - restore_cache:
+          keys:
+            - linux-gomod-cache-v1-{{ checksum "go.mod" }}
 
-      - run: go mod download
+      - run: go mod download
 
-      # Save go module cache if the go.mod file has changed
-      - save_cache:
-          key: go-multierror-modcache-v1-{{ checksum "go.mod" }}
-          paths:
-            - "/go/pkg/mod"
+      # Save go module cache if the go.mod file has changed
+      - save_cache:
+          key: linux-gomod-cache-v1-{{ checksum "go.mod" }}
+          paths:
+            - "/go/pkg/mod"
 
-      # check go fmt output because it does not report non-zero when there are fmt changes
-      - run:
-          name: check go fmt
-          command: |
-            files=$(go fmt ./...)
-            if [ -n "$files" ]; then
-              echo "The following file(s) do not conform to go fmt:"
-              echo "$files"
-              exit 1
-            fi
-      # run go tests with gotestsum
-      - run: |
-          PACKAGE_NAMES=$(go list ./...)
-          gotestsum --format=short-verbose --junitfile $TEST_RESULTS/gotestsum-report.xml -- $PACKAGE_NAMES
-      - store_test_results:
-          path: *TEST_RESULTS_PATH
-      - store_artifacts:
-          path: *TEST_RESULTS_PATH
+      # Check go fmt output because it does not report non-zero when there are fmt changes
+      - run:
+          name: check go fmt
+          command: |
+            files=$(go fmt ./...)
+            if [ -n "$files" ]; then
+              echo "The following file(s) do not conform to go fmt:"
+              echo "$files"
+              exit 1
+            fi
+      # Run go tests with gotestsum
+      - run-gotests:
+          cmd: "gotestsum"
+          platform: "linux"
+
+      # Save coverage report parts
+      - persist_to_workspace:
+          root: .
+          paths:
+            - linux_cov_*.part
+
+      - store_test_results:
+          path: *TEST_RESULTS_PATH
+      - store_artifacts:
+          path: *TEST_RESULTS_PATH
+
+  windows-tests:
+    executor: 
+      name: win/default
+      shell: bash --login -eo pipefail
+    environment:
+      <<: *ENVIRONMENT
+    working_directory: c:\gopath\src\github.com\hashicorp\go-multierror
+    parameters:
+      go-version:
+        type: string
+      gotestsum-version:
+        type: string
+    steps: 
+      - run: git config --global core.autocrlf false
+      - checkout
+      - attach_workspace:
+          at: .
+      - run: 
+          name: Setup (remove pre-installed go)
+          command: |
+            rm -rf "c:\Go"
+            mkdir -p $TEST_RESULTS_PATH/go-multierror
+      - restore_cache:
+          keys:
+            - win-golang-<< parameters.go-version >>-cache-v1
+            - win-gomod-cache-{{ checksum "go.mod" }}-v1
+
+      - run: 
+          name: Install go version << parameters.go-version >>
+          command: | 
+            if [ ! -d "c:\go" ]; then
+              echo "Cache not found, installing new version of go"
+              curl --fail --location https://dl.google.com/go/go<< parameters.go-version >>.windows-amd64.zip --output go.zip
+              unzip go.zip -d "/c"
+            fi
+      - run: 
+          command: go mod download
+
+      - save_cache:
+          key: win-golang-<< parameters.go-version >>-cache-v1
+          paths:
+            - /go
+
+      - save_cache:
+          key: win-gomod-cache-{{ checksum "go.mod" }}-v1
+          paths:
+            - c:\Windows\system32\config\systemprofile\go\pkg\mod
+
+      - run:
+          name: Install gotestsum
+          command: |
+            curl --fail --location https://github.com/gotestyourself/gotestsum/releases/download/v<< parameters.gotestsum-version >>/gotestsum_<< parameters.gotestsum-version >>_windows_amd64.tar.gz --output gotestsum.tar.gz
+            tar -xvzf gotestsum.tar.gz
+      - run-gotests:
+          cmd: "./gotestsum.exe"
+          platform: "win"
+
+      # Save coverage report parts
+      - persist_to_workspace:
+          root: .
+          paths:
+            - win_cov_*.part
+
+      - store_test_results:
+          path: *WIN_TEST_RESULTS
+      - store_artifacts:
+          path: *WIN_TEST_RESULTS
 
 workflows:
-  version: 2
-  test-and-build:
-    jobs:
-      - go-test
+  go-multierror:
+    jobs:
+      - linux-tests:
+          matrix:
+            parameters:
+              go-version: ["1.13", "1.14", "1.15"]
+          name: linux-test-go-<< matrix.go-version >>
+      - windows-tests:
+          matrix:
+            parameters:
+              go-version: ["1.13", "1.14", "1.15"]
+              gotestsum-version: ["1.6.2"]
+          name: win-test-go-<< matrix.go-version >>
diff --git a/README.md b/README.md
index bfca5c9..71dd308 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,10 @@
 # go-multierror
 
-[![Build Status](http://img.shields.io/travis/hashicorp/go-multierror.svg?style=flat-square)][travis]
-[![Go Documentation](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)][godocs]
+[![CircleCI](https://img.shields.io/circleci/build/github/hashicorp/go-multierror/master)](https://circleci.com/gh/hashicorp/go-multierror)
+[![Go Reference](https://pkg.go.dev/badge/github.com/hashicorp/go-multierror.svg)](https://pkg.go.dev/github.com/hashicorp/go-multierror)
+![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/hashicorp/go-multierror)
 
-[travis]: https://travis-ci.org/hashicorp/go-multierror
+[circleci]: https://app.circleci.com/pipelines/github/hashicorp/go-multierror
 [godocs]: https://pkg.go.dev/github.com/hashicorp/go-multierror
 
 `go-multierror` is a package for Go that provides a mechanism for
diff --git a/prefix_test.go b/prefix_test.go
index 1d4a6f6..849ec3a 100644
--- a/prefix_test.go
+++ b/prefix_test.go
@@ -27,6 +27,9 @@
 func TestPrefix_NonError(t *testing.T) {
 	original := errors.New("foo")
 	result := Prefix(original, "bar")
+	if result == nil {
+		t.Fatal("error result was nil")
+	}
 	if result.Error() != "bar foo" {
 		t.Fatalf("bad: %s", result)
 	}