@@ -3,6 +3,7 @@ package vm
33import (
44 "fmt"
55 "net/url"
6+ "os"
67 "reflect"
78 "testing"
89
@@ -1924,3 +1925,374 @@ make(struct {
19241925 }
19251926 runTests (t , tests , nil , & Options {Debug : true })
19261927}
1928+
1929+ func TestFuncWithStructs (t * testing.T ) {
1930+ os .Setenv ("ANKO_DEBUG" , "1" )
1931+ tests := []Test {
1932+ {
1933+ Script : `v = {"A":1, "B":2, "C":3, "D":4, "E":5}; rv = FuncWithIntStruct(v); A = rv.A` ,
1934+ Input : map [string ]interface {}{
1935+ "FuncWithIntStruct" : func (v struct {
1936+ A int8
1937+ B int16
1938+ C int32
1939+ D int64
1940+ E int
1941+ }) interface {} {
1942+ return v
1943+ },
1944+ },
1945+ RunOutput : int8 (1 ),
1946+ Output : map [string ]interface {}{
1947+ "rv" : struct {
1948+ A int8
1949+ B int16
1950+ C int32
1951+ D int64
1952+ E int
1953+ }{
1954+ 1 , 2 , 3 , 4 , 5 ,
1955+ },
1956+ },
1957+ },
1958+ {
1959+ Script : `v = {"A":3.14, "B":3.1415926}; rv = FuncWithFloatStruct(v); A = rv.A` ,
1960+ Input : map [string ]interface {}{
1961+ "FuncWithFloatStruct" : func (v struct {
1962+ A float32
1963+ B float64
1964+ }) interface {} {
1965+ return v
1966+ },
1967+ },
1968+ RunOutput : float32 (3.14 ),
1969+ Output : map [string ]interface {}{
1970+ "rv" : struct {
1971+ A float32
1972+ B float64
1973+ }{
1974+ 3.14 , 3.1415926 ,
1975+ },
1976+ },
1977+ },
1978+ {
1979+ Script : `v = {"A":true}; rv = FuncWithBoolStruct(v); A = rv.A` ,
1980+ Input : map [string ]interface {}{
1981+ "FuncWithBoolStruct" : func (v struct {
1982+ A bool
1983+ B bool
1984+ }) interface {} {
1985+ return v
1986+ },
1987+ },
1988+ RunOutput : bool (true ),
1989+ Output : map [string ]interface {}{
1990+ "rv" : struct {
1991+ A bool
1992+ B bool
1993+ }{
1994+ true , false ,
1995+ },
1996+ },
1997+ },
1998+ {
1999+ Script : `v = {"A":"A"}; rv = FuncWithStringStruct(v); A = rv.A` ,
2000+ Input : map [string ]interface {}{
2001+ "FuncWithStringStruct" : func (v struct {
2002+ A string
2003+ B string
2004+ }) interface {} {
2005+ return v
2006+ },
2007+ },
2008+ RunOutput : string ("A" ),
2009+ Output : map [string ]interface {}{
2010+ "rv" : struct {
2011+ A string
2012+ B string
2013+ }{
2014+ "A" , "" ,
2015+ },
2016+ },
2017+ },
2018+ {
2019+ Script : `A = ["1","2","3"]; B = [1,2,3]; C = [true, false]; v = {"A":A, "B":B, "C":C}; rv = FuncWithSliceStruct(v); A = rv.A` ,
2020+ Input : map [string ]interface {}{
2021+ "FuncWithSliceStruct" : func (v struct {
2022+ A []string
2023+ B []int
2024+ C []bool
2025+ }) interface {} {
2026+ return v
2027+ },
2028+ },
2029+ RunOutput : []string {"1" , "2" , "3" },
2030+ Output : map [string ]interface {}{
2031+ "rv" : struct {
2032+ A []string
2033+ B []int
2034+ C []bool
2035+ }{
2036+ A : []string {"1" , "2" , "3" },
2037+ B : []int {1 , 2 , 3 },
2038+ C : []bool {true , false },
2039+ },
2040+ },
2041+ },
2042+ {
2043+ // map only suport key is interface or string, value can any type
2044+ Script : `A = {"M":"am", "N":1}; B = {"M":"bm", "N":2}; C = {"M":"cm", "N":"cn"}; D = {"M":1, "N":2}; v = {"A": A,"B": B,"C": C,"D": D}; rv = FuncWithMapStruct(v);AM = rv.A["M"]; AN = rv.A["N"]; BM = rv.B["M"]; BN = rv.B["N"]; CM = rv.C["M"]; CN = rv.C["N"]; DM = rv.D["M"]; DN = rv.D["N"];` ,
2045+ Input : map [string ]interface {}{
2046+ "FuncWithMapStruct" : func (v struct {
2047+ A map [interface {}]interface {}
2048+ B map [string ]interface {}
2049+ C map [string ]string
2050+ D map [string ]int
2051+ }) interface {} {
2052+ return v
2053+ },
2054+ },
2055+ RunOutput : 2 ,
2056+ Output : map [string ]interface {}{
2057+ "AM" : "am" ,
2058+ "AN" : int64 (1 ),
2059+ "BM" : "bm" ,
2060+ "BN" : int64 (2 ),
2061+ "CM" : "cm" ,
2062+ "CN" : "cn" ,
2063+ "DM" : 1 ,
2064+ "DN" : 2 ,
2065+ },
2066+ },
2067+ {
2068+ Script : `d = ["1","2","3"]; e = {"M":"m", "N":1}; v = {"A": 1, "B": true, "C": "c", "D": d, "E":e}; rv = FuncWithCustomStruct(v); A=rv.A; B=rv.B; C=rv.C; D=rv.D; EM=rv.E["M"]; EN=rv.E["N"];` ,
2069+ Input : map [string ]interface {}{
2070+ "FuncWithCustomStruct" : func (v struct {
2071+ A int
2072+ B bool
2073+ C string
2074+ D []string
2075+ E map [interface {}]interface {}
2076+ }) interface {} {
2077+ return v
2078+ },
2079+ },
2080+ RunOutput : int64 (1 ),
2081+ Output : map [string ]interface {}{
2082+ "A" : int (1 ),
2083+ "B" : true ,
2084+ "C" : "c" ,
2085+ "D" : []string {"1" , "2" , "3" },
2086+ "EM" : "m" ,
2087+ "EN" : int64 (1 ),
2088+ },
2089+ },
2090+ {
2091+ Script : `d = ["1","2","3"]; e = {"M":1,"N":2}; v = {"A": {"AA":1}, "B": {"BB":true}, "C": {"CC":"c"}, "D": {"DD":d}, "E":{"EE":e}}; rv = FuncWithNestedCustomStruct(v); A=rv.A.AA; B=rv.B.BB; C=rv.C.CC; D=rv.D.DD; EM=rv.E.EE["M"]; EN=rv.E.EE["N"];` ,
2092+ Input : map [string ]interface {}{
2093+ "FuncWithNestedCustomStruct" : func (v struct {
2094+ A struct {
2095+ AA int
2096+ }
2097+ B struct {
2098+ BB bool
2099+ }
2100+ C struct {
2101+ CC string
2102+ }
2103+ D struct {
2104+ DD []string
2105+ }
2106+ E struct {
2107+ EE map [string ]int
2108+ }
2109+ }) interface {} {
2110+ return v
2111+ },
2112+ },
2113+ RunOutput : int (2 ),
2114+ Output : map [string ]interface {}{
2115+ "A" : 1 ,
2116+ "B" : true ,
2117+ "C" : "c" ,
2118+ "D" : []string {"1" , "2" , "3" },
2119+ "EM" : 1 ,
2120+ "EN" : 2 ,
2121+ },
2122+ },
2123+ {
2124+ Script : `d = ["1","2","3"]; e = {"M":true, "N":false}; v = {"A": {"AA":1}, "B": {"BB":true}, "C": {"CC":"c"}, "D": {"DD":d}, "E":{"EE":e}}; rv = FuncWithPointerCustomStruct(v); A=rv.A.AA; B=rv.B.BB; C=rv.C.CC; D=rv.D.DD; EM=rv.E.EE["M"]; EN=rv.E.EE["N"];` ,
2125+ Input : map [string ]interface {}{
2126+ "FuncWithPointerCustomStruct" : func (v * struct {
2127+ A * struct {
2128+ AA int
2129+ }
2130+ B * struct {
2131+ BB bool
2132+ }
2133+ C * struct {
2134+ CC string
2135+ }
2136+ D * struct {
2137+ DD []string
2138+ }
2139+ E * struct {
2140+ EE map [string ]bool
2141+ }
2142+ }) interface {} {
2143+ return v
2144+ },
2145+ },
2146+ RunOutput : false ,
2147+ Output : map [string ]interface {}{
2148+ "A" : 1 ,
2149+ "B" : true ,
2150+ "C" : "c" ,
2151+ "D" : []string {"1" , "2" , "3" },
2152+ "EM" : true ,
2153+ "EN" : false ,
2154+ },
2155+ },
2156+ {
2157+ Script : `a = [{"AA":"1"},{"AA":"2"}]; b = [{"BB":1},{"BB":2}]; v = {"A":a, "B":b}; rv = FuncWithSliceCustomStruct(v); A0 = rv.A[0].AA; A1 = rv.A[1].AA; B0 = rv.B[0].BB; B1 = rv.B[1].BB;` ,
2158+ Input : map [string ]interface {}{
2159+ "FuncWithSliceCustomStruct" : func (v struct {
2160+ A []struct {
2161+ AA string
2162+ }
2163+ B []* struct {
2164+ BB int
2165+ }
2166+ }) interface {} {
2167+ return v
2168+ },
2169+ },
2170+ RunOutput : 2 ,
2171+ Output : map [string ]interface {}{
2172+ "A0" : "1" ,
2173+ "A1" : "2" ,
2174+ "B0" : 1 ,
2175+ "B1" : 2 ,
2176+ },
2177+ },
2178+ {
2179+ Script : `a = {"M":{"AA":"1"}, 123:{"AA":"2"}}; b = {"M":{"BB":1},"N":{"BB":2}}; v = {"A":a, "B":b}; rv = FuncWithMapCustomStruct(v); AM = rv.A["M"].AA; AN = rv.A[123].AA; BM = rv.B["M"].BB; BN = rv.B["N"].BB;` ,
2180+ Input : map [string ]interface {}{
2181+ "FuncWithMapCustomStruct" : func (v struct {
2182+ A map [interface {}]struct {
2183+ AA string
2184+ }
2185+ B map [string ]* struct {
2186+ BB int
2187+ }
2188+ }) interface {} {
2189+ return v
2190+ },
2191+ },
2192+ RunOutput : 2 ,
2193+ Output : map [string ]interface {}{
2194+ "AM" : "1" ,
2195+ "AN" : "2" ,
2196+ "BM" : 1 ,
2197+ "BN" : 2 ,
2198+ },
2199+ },
2200+ {
2201+ Script : `v = [{"A":"A", "B":1, "C":false}, {"A":"A1", "B":2, "C":true}]; rv = FuncWithStructSlice(v); A0 = rv[0].A; B0 = rv[0].B; C0 = rv[0].C; A1 = rv[1].A; B1 = rv[1].B; C1 = rv[1].C;` ,
2202+ Input : map [string ]interface {}{
2203+ "FuncWithStructSlice" : func (v []struct {
2204+ A string
2205+ B int
2206+ C bool
2207+ }) interface {} {
2208+ return v
2209+ },
2210+ },
2211+ RunOutput : true ,
2212+ Output : map [string ]interface {}{
2213+ "A0" : "A" ,
2214+ "B0" : 1 ,
2215+ "C0" : false ,
2216+ "A1" : "A1" ,
2217+ "B1" : 2 ,
2218+ "C1" : true ,
2219+ },
2220+ },
2221+ {
2222+ Script : `v = {"M":{"A":"A", "B":1, "C":false}, "N":{"A":"A1", "B":2, "C":true}}; rv = FuncWithStructMap(v); MA = rv["M"].A; MB = rv["M"].B; MC = rv["M"].C; NA = rv["N"].A; NB = rv["N"].B; NC = rv["N"].C;` ,
2223+ Input : map [string ]interface {}{
2224+ "FuncWithStructMap" : func (v map [string ]struct {
2225+ A string
2226+ B int
2227+ C bool
2228+ }) interface {} {
2229+ return v
2230+ },
2231+ },
2232+ RunOutput : true ,
2233+ Output : map [string ]interface {}{
2234+ "MA" : "A" ,
2235+ "MB" : 1 ,
2236+ "MC" : false ,
2237+ "NA" : "A1" ,
2238+ "NB" : 2 ,
2239+ "NC" : true ,
2240+ },
2241+ },
2242+ }
2243+ runTests (t , tests , nil , & Options {Debug : true })
2244+ }
2245+
2246+ /* Benchmark test result
2247+ goos: linux
2248+ goarch: amd64
2249+ pkg: github.com/mattn/anko/vm
2250+ BenchmarkToStruct-16 199296 6095 ns/op 1672 B/op 43 allocs/op
2251+ */
2252+ func BenchmarkToStruct (b * testing.B ) {
2253+ rv := reflect .ValueOf (map [interface {}]interface {}{
2254+ "A" : true ,
2255+ "B" : 1 ,
2256+ "C" : 3.14 ,
2257+ "D" : "d" ,
2258+ "E" : []interface {}{"e1" , "e2" },
2259+ "F" : map [interface {}]interface {}{
2260+ "f1" : "f1" ,
2261+ "f2" : "f2" ,
2262+ },
2263+ "G" : map [interface {}]interface {}{
2264+ "A" : true ,
2265+ "B" : 1 ,
2266+ "C" : 3.14 ,
2267+ "D" : "d" ,
2268+ "E" : []interface {}{"e1" , "e2" },
2269+ "F" : map [interface {}]interface {}{
2270+ "f1" : "f1" ,
2271+ "f2" : "f2" ,
2272+ },
2273+ },
2274+ })
2275+ rt := reflect .TypeOf (struct {
2276+ A bool
2277+ B int
2278+ C float32
2279+ D string
2280+ E []string
2281+ F map [string ]string
2282+ G struct {
2283+ A bool
2284+ B int
2285+ C float32
2286+ D string
2287+ E []string
2288+ F map [string ]string
2289+ }
2290+ }{})
2291+
2292+ for i := 0 ; i < b .N ; i ++ {
2293+ _ , err := convertReflectValueToType (rv , rt )
2294+ if err != nil {
2295+ b .Errorf ("BenchmarkConvertReflectValueToStruct %v" , err )
2296+ }
2297+ }
2298+ }
0 commit comments