1*4947cdc7SCole Faust# Tests of Starlark 'struct' extension. 2*4947cdc7SCole Faust# This is not a standard feature and the Go and Starlark APIs may yet change. 3*4947cdc7SCole Faust 4*4947cdc7SCole Faustload("assert.star", "assert") 5*4947cdc7SCole Faust 6*4947cdc7SCole Faustassert.eq(str(struct), "<built-in function struct>") 7*4947cdc7SCole Faust 8*4947cdc7SCole Faust# struct is a constructor for "unbranded" structs. 9*4947cdc7SCole Fausts = struct(host = "localhost", port = 80) 10*4947cdc7SCole Faustassert.eq(s, s) 11*4947cdc7SCole Faustassert.eq(s, struct(host = "localhost", port = 80)) 12*4947cdc7SCole Faustassert.ne(s, struct(host = "localhost", port = 81)) 13*4947cdc7SCole Faustassert.eq(type(s), "struct") 14*4947cdc7SCole Faustassert.eq(str(s), 'struct(host = "localhost", port = 80)') 15*4947cdc7SCole Faustassert.eq(s.host, "localhost") 16*4947cdc7SCole Faustassert.eq(s.port, 80) 17*4947cdc7SCole Faustassert.fails(lambda : s.protocol, "struct has no .protocol attribute") 18*4947cdc7SCole Faustassert.eq(dir(s), ["host", "port"]) 19*4947cdc7SCole Faust 20*4947cdc7SCole Faust# Use gensym to create "branded" struct types. 21*4947cdc7SCole Fausthostport = gensym(name = "hostport") 22*4947cdc7SCole Faustassert.eq(type(hostport), "symbol") 23*4947cdc7SCole Faustassert.eq(str(hostport), "hostport") 24*4947cdc7SCole Faust 25*4947cdc7SCole Faust# Call the symbol to instantiate a new type. 26*4947cdc7SCole Fausthttp = hostport(host = "localhost", port = 80) 27*4947cdc7SCole Faustassert.eq(type(http), "struct") 28*4947cdc7SCole Faustassert.eq(str(http), 'hostport(host = "localhost", port = 80)') # includes name of constructor 29*4947cdc7SCole Faustassert.eq(http, http) 30*4947cdc7SCole Faustassert.eq(http, hostport(host = "localhost", port = 80)) 31*4947cdc7SCole Faustassert.ne(http, hostport(host = "localhost", port = 443)) 32*4947cdc7SCole Faustassert.eq(http.host, "localhost") 33*4947cdc7SCole Faustassert.eq(http.port, 80) 34*4947cdc7SCole Faustassert.fails(lambda : http.protocol, "hostport struct has no .protocol attribute") 35*4947cdc7SCole Faust 36*4947cdc7SCole Faustperson = gensym(name = "person") 37*4947cdc7SCole Faustbob = person(name = "bob", age = 50) 38*4947cdc7SCole Faustalice = person(name = "alice", city = "NYC") 39*4947cdc7SCole Faustassert.ne(http, bob) # different constructor symbols 40*4947cdc7SCole Faustassert.ne(bob, alice) # different fields 41*4947cdc7SCole Faust 42*4947cdc7SCole Fausthostport2 = gensym(name = "hostport") 43*4947cdc7SCole Faustassert.eq(hostport, hostport) 44*4947cdc7SCole Faustassert.ne(hostport, hostport2) # same name, different symbol 45*4947cdc7SCole Faustassert.ne(http, hostport2(host = "localhost", port = 80)) # equal fields but different ctor symbols 46*4947cdc7SCole Faust 47*4947cdc7SCole Faust# dir 48*4947cdc7SCole Faustassert.eq(dir(alice), ["city", "name"]) 49*4947cdc7SCole Faustassert.eq(dir(bob), ["age", "name"]) 50*4947cdc7SCole Faustassert.eq(dir(http), ["host", "port"]) 51*4947cdc7SCole Faust 52*4947cdc7SCole Faust# hasattr, getattr 53*4947cdc7SCole Faustassert.true(hasattr(alice, "city")) 54*4947cdc7SCole Faustassert.eq(hasattr(alice, "ageaa"), False) 55*4947cdc7SCole Faustassert.eq(getattr(alice, "city"), "NYC") 56*4947cdc7SCole Faust 57*4947cdc7SCole Faust# + 58*4947cdc7SCole Faustassert.eq(bob + bob, bob) 59*4947cdc7SCole Faustassert.eq(bob + alice, person(age = 50, city = "NYC", name = "alice")) 60*4947cdc7SCole Faustassert.eq(alice + bob, person(age = 50, city = "NYC", name = "bob")) # not commutative! a misfeature 61*4947cdc7SCole Faustassert.fails(lambda : alice + 1, "struct \\+ int") 62*4947cdc7SCole Faustassert.eq(http + http, http) 63*4947cdc7SCole Faustassert.fails(lambda : http + bob, "different constructors: hostport \\+ person") 64