From 4a38df1aadc64d8c854cd5fc8175ddd65cb98ee6 Mon Sep 17 00:00:00 2001 From: liujian Date: Mon, 6 Nov 2023 11:27:42 +0800 Subject: [PATCH] Update xdi --- src/xdi/container.go | 27 ++++++++++++++++++++++----- src/xdi/container_test.go | 21 +++++++++++++++++++-- src/xdi/object.go | 2 +- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/xdi/container.go b/src/xdi/container.go index ffb8c2f..552e649 100644 --- a/src/xdi/container.go +++ b/src/xdi/container.go @@ -1,6 +1,7 @@ package xdi import ( + "errors" "fmt" "reflect" "sync" @@ -33,7 +34,7 @@ type Container struct { func (t *Container) Provide(objects ...*Object) error { for _, o := range objects { if _, ok := t.tidyObjects.Load(o.Name); ok { - return fmt.Errorf("error: object '%s' existing", o.Name) + return fmt.Errorf("xdi: object '%s' existing", o.Name) } t.tidyObjects.Store(o.Name, o) } @@ -43,20 +44,36 @@ func (t *Container) Provide(objects ...*Object) error { func (t *Container) Object(name string) (*Object, error) { v, ok := t.tidyObjects.Load(name) if !ok { - return nil, fmt.Errorf("error: object '%s' not found", name) + return nil, fmt.Errorf("xdi: object '%s' not found", name) } obj := v.(*Object) return obj, nil } -func (t *Container) Populate(name string, ptr interface{}) error { +func (t *Container) Populate(name string, ptr interface{}) (err error) { + defer func() { + if e := recover(); e != nil { + err = errors.New(fmt.Sprint(e)) + } + }() + obj, err := t.Object(name) if err != nil { return err } - ptrCopy := func(to, from interface{}) { - reflect.ValueOf(to).Elem().Set(reflect.ValueOf(from)) + + if reflect.ValueOf(ptr).Kind() != reflect.Ptr { + return errors.New("xdi: argument can only be pointer type") } + + ptrCopy := func(ptr, newValue interface{}) { + v := reflect.ValueOf(ptr) + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + v.Set(reflect.ValueOf(newValue)) + } + if !obj.NewEverytime { refresher := &obj.refresher if p, ok := t.instances.Load(name); ok && !refresher.status() { diff --git a/src/xdi/container_test.go b/src/xdi/container_test.go index aefa1ad..af39ed2 100644 --- a/src/xdi/container_test.go +++ b/src/xdi/container_test.go @@ -51,16 +51,33 @@ func TestPopulate(t *testing.T) { } _ = c.Provide(objs...) + // 测试单例 + var f1 *foo + _ = c.Populate("foo", &f1) + var f2 *foo + _ = c.Populate("foo", &f2) + a.Equal(fmt.Sprintf("%p", f1), fmt.Sprintf("%p", f2)) + + // 错误使用测试 + var f3 foo + err := c.Populate("foo", f3) // 非指针 + a.Contains(err.Error(), "can only be pointer type") + var f4 foo + err = c.Populate("foo", &f4) // New函数返回的指针,但是f3为引用 [panic: reflect.Set: value of type *xdi.foo is not assignable to type xdi.foo] + a.Contains(err.Error(), "is not assignable to") + + // 测试嵌套依赖 var f *foo _ = c.Populate("foo", &f) text := fmt.Sprintf("%#v \n", f.Client) a.Contains(text, "Timeout:10000000000") + // 测试多次失败场景 var i interface{} - err := c.Populate("bar", &i) + err = c.Populate("bar", &i) a.Equal(err, errors.New("error")) err = c.Populate("bar", &i) - a.Equal(err, errors.New("error")) // 测试多次失败场景 + a.Equal(err, errors.New("error")) } func TestSingletonConcurrency(t *testing.T) { diff --git a/src/xdi/object.go b/src/xdi/object.go index c02a9d8..9700ca5 100644 --- a/src/xdi/object.go +++ b/src/xdi/object.go @@ -18,7 +18,7 @@ type Object struct { func (t *Object) Refresh() error { if t.NewEverytime { - return fmt.Errorf("error: '%s' is NewEverytime, unable to refresh", t.Name) + return fmt.Errorf("xdi: '%s' is NewEverytime, unable to refresh", t.Name) } t.refresher.on() return nil