github.com/benma/gogen@v0.0.0-20160826115606-cf49914b915a/unmarshalmap/testunmarshalmap/test.go (about)

     1  package testunmarshalmap
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"reflect"
     8  	"strconv"
     9  	"strings"
    10  	"testing"
    11  )
    12  
    13  // Debug indicates we should log debugging information
    14  var Debug bool
    15  
    16  type unmarshalMapper interface {
    17  	UnmarshalMap(map[string]interface{}) error
    18  }
    19  
    20  // Run tests that UnmarshalMap unmarshalls all fields
    21  func Run(t *testing.T, v unmarshalMapper) {
    22  	// make an empty variable of the same type as v
    23  	n := empty(t, v)
    24  
    25  	// fill the variable with data
    26  	fill(t, v)
    27  
    28  	// generate a map[string]interface{}
    29  	m := generateMap(t, v)
    30  
    31  	// unmarshal generated map into the empty variable
    32  	n.UnmarshalMap(m)
    33  
    34  	if !reflect.DeepEqual(v, n) {
    35  		t.Fatalf("UnmarshalMap() method from %T out of date. regenerate the code", v)
    36  	}
    37  }
    38  
    39  func empty(t *testing.T, v unmarshalMapper) unmarshalMapper {
    40  	n := makeNew(t, v)
    41  	u, ok := n.(unmarshalMapper)
    42  	if !ok {
    43  		t.Fatalf("%T should implement UnmarshalMap", n)
    44  	}
    45  	return u
    46  }
    47  
    48  func generateMap(t *testing.T, v unmarshalMapper) map[string]interface{} {
    49  	var buf bytes.Buffer
    50  	err := json.NewEncoder(&buf).Encode(v)
    51  	if err != nil {
    52  		t.Fatal(err)
    53  	}
    54  	var m map[string]interface{}
    55  	err = json.NewDecoder(&buf).Decode(&m)
    56  	if err != nil {
    57  		t.Fatal(err)
    58  	}
    59  	return m
    60  }
    61  
    62  func fill(t *testing.T, v interface{}) {
    63  	val := reflect.ValueOf(v)
    64  	fillReflect(t, "", val)
    65  }
    66  
    67  func makeNew(t *testing.T, v interface{}) interface{} {
    68  	typ := reflect.TypeOf(v).Elem()
    69  	val := reflect.New(typ)
    70  	return val.Interface()
    71  }
    72  
    73  func fillReflect(t *testing.T, scope string, val reflect.Value) {
    74  	if val.Kind() == reflect.Ptr {
    75  		val = val.Elem()
    76  	}
    77  	typ := val.Type()
    78  	if !val.IsValid() {
    79  		t.Fatalf("invalid")
    80  	}
    81  	if Debug {
    82  		t.Logf("%s %s", scope, typ.Kind())
    83  	}
    84  
    85  	for i := 0; i < typ.NumField(); i++ {
    86  		f := typ.Field(i)
    87  		// Skip omitted fields
    88  		if tag := strings.Split(f.Tag.Get("json"), ","); len(tag) > 0 && tag[0] == "-" {
    89  			continue
    90  		}
    91  		if Debug {
    92  			t.Logf("%s%s %s", scope, f.Name, f.Type.Kind())
    93  		}
    94  		v := val.Field(i)
    95  		fillValue(t, scope+f.Name+".", v)
    96  	}
    97  }
    98  
    99  func fillValue(t *testing.T, scope string, v reflect.Value) {
   100  	kind := v.Type().Kind()
   101  	if kind == reflect.Ptr {
   102  		v.Set(reflect.New(v.Type().Elem()))
   103  		v = v.Elem()
   104  		kind = v.Kind()
   105  	}
   106  	switch kind {
   107  	case reflect.Ptr:
   108  		t.Fatalf("%s should have been de-referenced", scope)
   109  	case reflect.Interface, reflect.Chan, reflect.Func, reflect.Complex64, reflect.Complex128, reflect.Uintptr:
   110  		t.Fatalf("%s cannot unmarshall %s", scope, kind)
   111  	case reflect.Bool:
   112  		v.SetBool(true)
   113  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   114  		v.SetInt(newInt())
   115  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   116  		v.SetUint(newUint())
   117  	case reflect.Float32, reflect.Float64:
   118  		v.SetFloat(newFloat())
   119  	case reflect.Array:
   120  		l := v.Cap()
   121  		for i := 0; i < l; i++ {
   122  			fillValue(t, fmt.Sprintf("%s[%d].", scope, i), v.Index(i))
   123  		}
   124  	case reflect.Slice:
   125  		l := int(newInt())/2 + 1
   126  		s := reflect.MakeSlice(v.Type(), l, l)
   127  		v.Set(s)
   128  		for i := 0; i < l; i++ {
   129  			fillValue(t, fmt.Sprintf("%s[%d].", scope, i), s.Index(i))
   130  		}
   131  	// case reflect.Map:
   132  	// 	t.Fatalf("%s unmarshalling maps is still pending", scope)
   133  	case reflect.String:
   134  		v.SetString(newStr())
   135  	case reflect.Struct:
   136  		fillReflect(t, scope, v)
   137  	default:
   138  		t.Fatalf("gounmarshalmap is missing support for %s unmarshalling", kind)
   139  	}
   140  }
   141  
   142  var i uint64
   143  
   144  func newInt() int64 {
   145  	i++
   146  	return int64(i)
   147  }
   148  
   149  func newFloat() float64 {
   150  	i++
   151  	return float64(i)
   152  }
   153  
   154  func newUint() uint64 {
   155  	i++
   156  	return i
   157  }
   158  
   159  func newStr() string {
   160  	i++
   161  	return strconv.FormatInt(int64(i), 10)
   162  }