|
8 | 8 | "bytes"
|
9 | 9 | "encoding/hex"
|
10 | 10 | "fmt"
|
| 11 | + "io/ioutil" |
11 | 12 | "reflect"
|
12 | 13 | "strings"
|
13 | 14 | "testing"
|
@@ -831,30 +832,81 @@ func TestPtrToMapOfMap(t *testing.T) {
|
831 | 832 |
|
832 | 833 | // A top-level nil pointer generates a panic with a helpful string-valued message.
|
833 | 834 | func TestTopLevelNilPointer(t *testing.T) {
|
834 |
| - errMsg := topLevelNilPanic(t) |
835 |
| - if errMsg == "" { |
| 835 | + var ip *int |
| 836 | + encodeErr, panicErr := encodeAndRecover(ip) |
| 837 | + if encodeErr != nil { |
| 838 | + t.Fatal("error in encode:", encodeErr) |
| 839 | + } |
| 840 | + if panicErr == nil { |
836 | 841 | t.Fatal("top-level nil pointer did not panic")
|
837 | 842 | }
|
| 843 | + errMsg := panicErr.Error() |
838 | 844 | if !strings.Contains(errMsg, "nil pointer") {
|
839 | 845 | t.Fatal("expected nil pointer error, got:", errMsg)
|
840 | 846 | }
|
841 | 847 | }
|
842 | 848 |
|
843 |
| -func topLevelNilPanic(t *testing.T) (panicErr string) { |
| 849 | +func encodeAndRecover(value interface{}) (encodeErr, panicErr error) { |
844 | 850 | defer func() {
|
845 | 851 | e := recover()
|
846 |
| - if err, ok := e.(string); ok { |
847 |
| - panicErr = err |
| 852 | + if e != nil { |
| 853 | + switch err := e.(type) { |
| 854 | + case error: |
| 855 | + panicErr = err |
| 856 | + default: |
| 857 | + panicErr = fmt.Errorf("%v", err) |
| 858 | + } |
848 | 859 | }
|
849 | 860 | }()
|
850 |
| - var ip *int |
851 |
| - buf := new(bytes.Buffer) |
852 |
| - if err := NewEncoder(buf).Encode(ip); err != nil { |
853 |
| - t.Fatal("error in encode:", err) |
854 |
| - } |
| 861 | + |
| 862 | + encodeErr = NewEncoder(ioutil.Discard).Encode(value) |
855 | 863 | return
|
856 | 864 | }
|
857 | 865 |
|
| 866 | +func TestNilPointerPanics(t *testing.T) { |
| 867 | + var ( |
| 868 | + nilStringPtr *string |
| 869 | + intMap = make(map[int]int) |
| 870 | + intMapPtr = &intMap |
| 871 | + nilIntMapPtr *map[int]int |
| 872 | + zero int |
| 873 | + nilBoolChannel chan bool |
| 874 | + nilBoolChannelPtr *chan bool |
| 875 | + nilStringSlice []string |
| 876 | + stringSlice = make([]string, 1) |
| 877 | + nilStringSlicePtr *[]string |
| 878 | + ) |
| 879 | + |
| 880 | + testCases := []struct { |
| 881 | + value interface{} |
| 882 | + mustPanic bool |
| 883 | + }{ |
| 884 | + {nilStringPtr, true}, |
| 885 | + {intMap, false}, |
| 886 | + {intMapPtr, false}, |
| 887 | + {nilIntMapPtr, true}, |
| 888 | + {zero, false}, |
| 889 | + {nilStringSlice, false}, |
| 890 | + {stringSlice, false}, |
| 891 | + {nilStringSlicePtr, true}, |
| 892 | + {nilBoolChannel, false}, |
| 893 | + {nilBoolChannelPtr, true}, |
| 894 | + } |
| 895 | + |
| 896 | + for _, tt := range testCases { |
| 897 | + _, panicErr := encodeAndRecover(tt.value) |
| 898 | + if tt.mustPanic { |
| 899 | + if panicErr == nil { |
| 900 | + t.Errorf("expected panic with input %#v, did not panic", tt.value) |
| 901 | + } |
| 902 | + continue |
| 903 | + } |
| 904 | + if panicErr != nil { |
| 905 | + t.Fatalf("expected no panic with input %#v, got panic=%v", tt.value, panicErr) |
| 906 | + } |
| 907 | + } |
| 908 | +} |
| 909 | + |
858 | 910 | func TestNilPointerInsideInterface(t *testing.T) {
|
859 | 911 | var ip *int
|
860 | 912 | si := struct {
|
|
0 commit comments