github.com/cloudbase/juju-core@v0.0.0-20140504232958-a7271ac7912f/testing/checkers/deepequal_test.go (about)

     1  // Copied with small adaptations from the reflect package in the
     2  // Go source tree. We use testing rather than gocheck to preserve
     3  // as much source equivalence as possible.
     4  
     5  // TODO tests for error messages
     6  
     7  // Copyright 2009 The Go Authors. All rights reserved.
     8  // Use of this source code is governed by a BSD-style
     9  // license that can be found in the LICENSE file.
    10  
    11  package checkers_test
    12  
    13  import (
    14  	"regexp"
    15  	"testing"
    16  
    17  	"launchpad.net/juju-core/testing/checkers"
    18  )
    19  
    20  func deepEqual(a1, a2 interface{}) bool {
    21  	ok, _ := checkers.DeepEqual(a1, a2)
    22  	return ok
    23  }
    24  
    25  type Basic struct {
    26  	x int
    27  	y float32
    28  }
    29  
    30  type NotBasic Basic
    31  
    32  type DeepEqualTest struct {
    33  	a, b interface{}
    34  	eq   bool
    35  	msg  string
    36  }
    37  
    38  // Simple functions for DeepEqual tests.
    39  var (
    40  	fn1 func()             // nil.
    41  	fn2 func()             // nil.
    42  	fn3 = func() { fn1() } // Not nil.
    43  )
    44  
    45  var deepEqualTests = []DeepEqualTest{
    46  	// Equalities
    47  	{nil, nil, true, ""},
    48  	{1, 1, true, ""},
    49  	{int32(1), int32(1), true, ""},
    50  	{0.5, 0.5, true, ""},
    51  	{float32(0.5), float32(0.5), true, ""},
    52  	{"hello", "hello", true, ""},
    53  	{make([]int, 10), make([]int, 10), true, ""},
    54  	{&[3]int{1, 2, 3}, &[3]int{1, 2, 3}, true, ""},
    55  	{Basic{1, 0.5}, Basic{1, 0.5}, true, ""},
    56  	{error(nil), error(nil), true, ""},
    57  	{map[int]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, true, ""},
    58  	{fn1, fn2, true, ""},
    59  
    60  	// Inequalities
    61  	{1, 2, false, `mismatch at top level: unequal; obtained 1; expected 2`},
    62  	{int32(1), int32(2), false, `mismatch at top level: unequal; obtained 1; expected 2`},
    63  	{0.5, 0.6, false, `mismatch at top level: unequal; obtained 0\.5; expected 0\.6`},
    64  	{float32(0.5), float32(0.6), false, `mismatch at top level: unequal; obtained 0\.5; expected 0\.6`},
    65  	{"hello", "hey", false, `mismatch at top level: unequal; obtained "hello"; expected "hey"`},
    66  	{make([]int, 10), make([]int, 11), false, `mismatch at top level: length mismatch, 10 vs 11; obtained \[\]int\{0, 0, 0, 0, 0, 0, 0, 0, 0, 0\}; expected \[\]int\{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\}`},
    67  	{&[3]int{1, 2, 3}, &[3]int{1, 2, 4}, false, `mismatch at \(\*\)\[2\]: unequal; obtained 3; expected 4`},
    68  	{Basic{1, 0.5}, Basic{1, 0.6}, false, `mismatch at \.y: unequal; obtained 0\.5; expected 0\.6`},
    69  	{Basic{1, 0}, Basic{2, 0}, false, `mismatch at \.x: unequal; obtained 1; expected 2`},
    70  	{map[int]string{1: "one", 3: "two"}, map[int]string{2: "two", 1: "one"}, false, `mismatch at \[3\]: validity mismatch; obtained "two"; expected <nil>`},
    71  	{map[int]string{1: "one", 2: "txo"}, map[int]string{2: "two", 1: "one"}, false, `mismatch at \[2\]: unequal; obtained "txo"; expected "two"`},
    72  	{map[int]string{1: "one"}, map[int]string{2: "two", 1: "one"}, false, `mismatch at top level: length mismatch, 1 vs 2; obtained map\[int\]string\{1:"one"\}; expected map\[int\]string\{2:"two", 1:"one"\}`},
    73  	{map[int]string{2: "two", 1: "one"}, map[int]string{1: "one"}, false, `mismatch at top level: length mismatch, 2 vs 1; obtained map\[int\]string\{2:"two", 1:"one"\}; expected map\[int\]string\{1:"one"\}`},
    74  	{nil, 1, false, `mismatch at top level: nil vs non-nil mismatch; obtained <nil>; expected 1`},
    75  	{1, nil, false, `mismatch at top level: nil vs non-nil mismatch; obtained 1; expected <nil>`},
    76  	{fn1, fn3, false, `mismatch at top level: non-nil functions; obtained \(func\(\)\)\(nil\); expected \(func\(\)\)\(0x[0-9a-f]+\)`},
    77  	{fn3, fn3, false, `mismatch at top level: non-nil functions; obtained \(func\(\)\)\(0x[0-9a-f]+\); expected \(func\(\)\)\(0x[0-9a-f]+\)`},
    78  
    79  	// Nil vs empty: they're the same (difference from normal DeepEqual)
    80  	{[]int{}, []int(nil), true, ""},
    81  	{[]int{}, []int{}, true, ""},
    82  	{[]int(nil), []int(nil), true, ""},
    83  
    84  	// Mismatched types
    85  	{1, 1.0, false, `mismatch at top level: type mismatch int vs float64; obtained 1; expected 1`},
    86  	{int32(1), int64(1), false, `mismatch at top level: type mismatch int32 vs int64; obtained 1; expected 1`},
    87  	{0.5, "hello", false, `mismatch at top level: type mismatch float64 vs string; obtained 0\.5; expected "hello"`},
    88  	{[]int{1, 2, 3}, [3]int{1, 2, 3}, false, `mismatch at top level: type mismatch \[\]int vs \[3\]int; obtained \[\]int\{1, 2, 3\}; expected \[3\]int\{1, 2, 3\}`},
    89  	{&[3]interface{}{1, 2, 4}, &[3]interface{}{1, 2, "s"}, false, `mismatch at \(\*\)\[2\]: type mismatch int vs string; obtained 4; expected "s"`},
    90  	{Basic{1, 0.5}, NotBasic{1, 0.5}, false, `mismatch at top level: type mismatch checkers_test\.Basic vs checkers_test\.NotBasic; obtained checkers_test\.Basic\{x:1, y:0\.5\}; expected checkers_test\.NotBasic\{x:1, y:0\.5\}`},
    91  	{map[uint]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, false, `mismatch at top level: type mismatch map\[uint\]string vs map\[int\]string; obtained map\[uint\]string\{0x1:"one", 0x2:"two"\}; expected map\[int\]string\{2:"two", 1:"one"\}`},
    92  }
    93  
    94  func TestDeepEqual(t *testing.T) {
    95  	for _, test := range deepEqualTests {
    96  		r, err := checkers.DeepEqual(test.a, test.b)
    97  		if r != test.eq {
    98  			t.Errorf("deepEqual(%v, %v) = %v, want %v", test.a, test.b, r, test.eq)
    99  		}
   100  		if test.eq {
   101  			if err != nil {
   102  				t.Errorf("deepEqual(%v, %v): unexpected error message %q when equal", test.a, test.b, err)
   103  			}
   104  		} else {
   105  			if ok, _ := regexp.MatchString(test.msg, err.Error()); !ok {
   106  				t.Errorf("deepEqual(%v, %v); unexpected error %q, want %q", test.a, test.b, err.Error(), test.msg)
   107  			}
   108  		}
   109  	}
   110  }
   111  
   112  type Recursive struct {
   113  	x int
   114  	r *Recursive
   115  }
   116  
   117  func TestDeepEqualRecursiveStruct(t *testing.T) {
   118  	a, b := new(Recursive), new(Recursive)
   119  	*a = Recursive{12, a}
   120  	*b = Recursive{12, b}
   121  	if !deepEqual(a, b) {
   122  		t.Error("deepEqual(recursive same) = false, want true")
   123  	}
   124  }
   125  
   126  type _Complex struct {
   127  	a int
   128  	b [3]*_Complex
   129  	c *string
   130  	d map[float64]float64
   131  }
   132  
   133  func TestDeepEqualComplexStruct(t *testing.T) {
   134  	m := make(map[float64]float64)
   135  	stra, strb := "hello", "hello"
   136  	a, b := new(_Complex), new(_Complex)
   137  	*a = _Complex{5, [3]*_Complex{a, b, a}, &stra, m}
   138  	*b = _Complex{5, [3]*_Complex{b, a, a}, &strb, m}
   139  	if !deepEqual(a, b) {
   140  		t.Error("deepEqual(complex same) = false, want true")
   141  	}
   142  }
   143  
   144  func TestDeepEqualComplexStructInequality(t *testing.T) {
   145  	m := make(map[float64]float64)
   146  	stra, strb := "hello", "helloo" // Difference is here
   147  	a, b := new(_Complex), new(_Complex)
   148  	*a = _Complex{5, [3]*_Complex{a, b, a}, &stra, m}
   149  	*b = _Complex{5, [3]*_Complex{b, a, a}, &strb, m}
   150  	if deepEqual(a, b) {
   151  		t.Error("deepEqual(complex different) = true, want false")
   152  	}
   153  }
   154  
   155  type UnexpT struct {
   156  	m map[int]int
   157  }
   158  
   159  func TestDeepEqualUnexportedMap(t *testing.T) {
   160  	// Check that DeepEqual can look at unexported fields.
   161  	x1 := UnexpT{map[int]int{1: 2}}
   162  	x2 := UnexpT{map[int]int{1: 2}}
   163  	if !deepEqual(&x1, &x2) {
   164  		t.Error("deepEqual(x1, x2) = false, want true")
   165  	}
   166  
   167  	y1 := UnexpT{map[int]int{2: 3}}
   168  	if deepEqual(&x1, &y1) {
   169  		t.Error("deepEqual(x1, y1) = true, want false")
   170  	}
   171  }