Browse Source

Fix panic due to mismatched types

Signed-off-by: Chun Chen <ramichen@tencent.com>
Chun Chen 10 years ago
parent
commit
c09fe6a7c1
2 changed files with 26 additions and 0 deletions
  1. 15 0
      libnetwork/options/options.go
  2. 11 0
      libnetwork/options/options_test.go

+ 15 - 0
libnetwork/options/options.go

@@ -29,6 +29,18 @@ func (e CannotSetFieldError) Error() string {
 	return fmt.Sprintf("cannot set field %q of type %q", e.Field, e.Type)
 }
 
+// TypeMismatchError is the error returned when the type of the generic value
+// for a field mismatches the type of the destination structure.
+type TypeMismatchError struct {
+	Field      string
+	ExpectType string
+	ActualType string
+}
+
+func (e TypeMismatchError) Error() string {
+	return fmt.Sprintf("type mismatch, field %s require type %v, actual type %v", e.Field, e.ExpectType, e.ActualType)
+}
+
 // Generic is an basic type to store arbitrary settings.
 type Generic map[string]interface{}
 
@@ -62,6 +74,9 @@ func GenerateFromModel(options Generic, model interface{}) (interface{}, error)
 		if !field.CanSet() {
 			return nil, CannotSetFieldError{name, resType.String()}
 		}
+		if reflect.TypeOf(value) != field.Type() {
+			return nil, TypeMismatchError{name, field.Type().String(), reflect.TypeOf(value).String()}
+		}
 		field.Set(reflect.ValueOf(value))
 	}
 

+ 11 - 0
libnetwork/options/options_test.go

@@ -95,3 +95,14 @@ func TestFieldCannotBeSet(t *testing.T) {
 		t.Fatalf("expected %q in error message, got %s", expected, err.Error())
 	}
 }
+
+func TestTypeMismatchError(t *testing.T) {
+	type Model struct{ Foo int }
+	_, err := GenerateFromModel(Generic{"Foo": "bar"}, Model{})
+
+	if _, ok := err.(TypeMismatchError); !ok {
+		t.Fatalf("expected TypeMismatchError, got %#v", err)
+	} else if expected := "type mismatch"; !strings.Contains(err.Error(), expected) {
+		t.Fatalf("expected %q in error message, got %s", expected, err.Error())
+	}
+}