1: %% 2: %% %CopyrightBegin% 3: %% 4: %% Copyright Ericsson AB 1997-2011. All Rights Reserved. 5: %% 6: %% The contents of this file are subject to the Erlang Public License, 7: %% Version 1.1, (the "License"); you may not use this file except in 8: %% compliance with the License. You should have received a copy of the 9: %% Erlang Public License along with this software. If not, it can be 10: %% retrieved online at http://www.erlang.org/. 11: %% 12: %% Software distributed under the License is distributed on an "AS IS" 13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 14: %% the License for the specific language governing rights and limitations 15: %% under the License. 16: %% 17: %% %CopyrightEnd% 18: %% 19: %% 20: %%----------------------------------------------------------------- 21: %% 22: %% Description: 23: %% Test suite for corba/boa/object/orber API functions 24: %% 25: %%----------------------------------------------------------------- 26: -module(corba_SUITE). 27: 28: -include_lib("test_server/include/test_server.hrl"). 29: -include_lib("orber/include/corba.hrl"). 30: -include_lib("orber/COSS/CosNaming/CosNaming.hrl"). 31: -include_lib("orber/src/orber_iiop.hrl"). 32: 33: 34: -define(default_timeout, ?t:minutes(5)). 35: 36: -define(match(ExpectedRes,Expr), 37: fun() -> 38: AcTuAlReS = (catch (Expr)), 39: case AcTuAlReS of 40: ExpectedRes -> 41: io:format("------ CORRECT RESULT ------~n~p~n", 42: [AcTuAlReS]), 43: AcTuAlReS; 44: _ -> 45: io:format("###### ERROR ERROR ######~nRESULT: ~p~n", 46: [AcTuAlReS]), 47: exit(AcTuAlReS) 48: end 49: end()). 50: 51: %%----------------------------------------------------------------- 52: %% External exports 53: %%----------------------------------------------------------------- 54: -export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]). 55: 56: %%----------------------------------------------------------------- 57: %% Internal exports 58: %%----------------------------------------------------------------- 59: -export([pseudo_calls/2, pseudo_casts/2]). 60: -compile(export_all). 61: 62: %%----------------------------------------------------------------- 63: %% Func: all/1 64: %% Args: 65: %% Returns: 66: %%----------------------------------------------------------------- 67: suite() -> [{ct_hooks,[ts_install_cth]}]. 68: 69: all() -> 70: cases(). 71: 72: groups() -> 73: []. 74: 75: init_per_group(_GroupName, Config) -> 76: Config. 77: 78: end_per_group(_GroupName, Config) -> 79: Config. 80: 81: 82: cases() -> 83: [exception_info_api, corba_api, object_api, orber_api, 84: orber_objectkeys_api, orber_pseudo_objects, 85: callback_ok_api, callback_arity_api, 86: callback_module_api, callback_function_api, 87: callback_precond_api, callback_postcond_api, 88: callback_exit_api, callback_badarith_api, 89: callback_case_clause_api, callback_function_clause_api]. 90: 91: %% boa_api, request, locate_request, locate_reply]. 92: 93: %%----------------------------------------------------------------- 94: %% Init and cleanup functions. 95: %%----------------------------------------------------------------- 96: 97: init_per_testcase(_Case, Config) -> 98: Path = code:which(?MODULE), 99: code:add_pathz(filename:join(filename:dirname(Path), "idl_output")), 100: ?line Dog=test_server:timetrap(?default_timeout), 101: [{watchdog, Dog}|Config]. 102: 103: 104: end_per_testcase(_Case, Config) -> 105: Path = code:which(?MODULE), 106: code:del_path(filename:join(filename:dirname(Path), "idl_output")), 107: Dog = ?config(watchdog, Config), 108: test_server:timetrap_cancel(Dog), 109: ok. 110: 111: init_per_suite(Config) -> 112: corba:orb_init([{orber_debug_level, 10}, {giop_version, {1,2}}, 113: {iiop_port, 0}]), 114: mnesia:delete_schema([node()]), 115: mnesia:create_schema([node()]), 116: orber:install([node()]), 117: application:start(mnesia), 118: application:start(orber), 119: if 120: is_list(Config) -> 121: Config; 122: true -> 123: exit("Config not a list") 124: end. 125: 126: end_per_suite(Config) -> 127: application:stop(orber), 128: application:stop(mnesia), 129: mnesia:delete_schema([node()]), 130: Config. 131: 132: %%----------------------------------------------------------------- 133: %% API tests for pseudo interface CORBA 134: %%----------------------------------------------------------------- 135: corba_api(doc) -> ["CORBA API tests", ""]; 136: corba_api(suite) -> []; 137: corba_api(_) -> 138: NIL = corba:create_nil_objref(), 139: ?line ok = corba:dispose(NIL), 140: ?line NS = corba:resolve_initial_references("NameService"), 141: ?line List = corba:list_initial_services(), 142: ?line ["NameService"] = List, 143: ?line NSstring = corba:object_to_string(NS), 144: ?line NS1 = corba:string_to_object(NSstring), 145: ?line NSstring = corba:object_to_string(NS1), 146: ?line true = corba:add_initial_service("MyData", NS), 147: ?line NS = corba:resolve_initial_references("MyData"), 148: ?line [_,_] = corba:list_initial_services(), 149: ?line false = corba:remove_initial_service("Wrong"), 150: ?line NIL = corba:resolve_initial_references("Wrong"), 151: ?line NS = corba:string_to_object("corbaloc:rir:/MyData"), 152: ?line true = corba:remove_initial_service("MyData"), 153: ?line ["NameService"] = corba:list_initial_services(), 154: 155: %% This is a collection of different stringified IOR:s (correct & incorrect) 156: %% which we use to test IOR encode/decode. 157: ?line IOR1 = ?match({'IOP_IOR',_,_}, corba:string_to_object("IOR:000303030000000d49444c3a746573743a312e3000030303000000040000000000000100000102010000000a3132372e302e302e31009d610000002dabacab3131303432343836383731005f526f6f74504f4100414c4c5f504f410000cafebabe3e2316570000000003030300000002000000210000007800010202000000010040020200000022000000080003030300000000004000400000000806066781020101010000001b0401000806066781020101010000000b40616469726f6e2e636f6d010400000000000000000000020000000806066781020101010000000b06092a864886f712010202010000000f000000010000002c00030303000100010000000400010020000101090001010005010001000101090000000200010100050100010000000000000184000102010000000a3132372e302e302e310000000000002dabacab3131303432343836383731005f526f6f74504f4100414c4c5f504f410000cafebabe3e231657000000000303030000000300000021000000ec000102020000000200060202000000240000001c0001006600060202000000010000000a3132372e302e302e31009d600000000000000000000000000400000000000000000000020000000806066781020101010000000b06092a864886f712010202010000000f00460202000000240000001c0001006600060202000000010000000a3132372e302e302e31009d62004000400000000806066781020101010000001b0401000806066781020101010000000b40616469726f6e2e636f6d010400000000000000000000020000000806066781020101010000000b06092a864886f712010202010000000f00000014000000080001006600069d5e000000010000002c000303030001000100000004000100200001010900010100050100010001010900000002000101000501000100000000000000dc000102010000000a3132372e302e302e31009d5f0000002dabacab3131303432343836383731005f526f6f74504f4100414c4c5f504f410000cafebabe3e23165700000000030303000000020000002100000054000102020000000100000202000000220000000800030303000000000000000000000000000000000400000000000000000000020000000806066781020101010000000b06092a864886f712010202010000000f000000010000002c00030303000100010000000400010020000101090001010005010001000101090000000200010100050100010000000000000080000102010000000a3132372e302e302e31009d5d0000002dabacab3131303432343836383731005f526f6f74504f4100414c4c5f504f410000cafebabe3e2316570000000003030300000001000000010000002c0003030300010001000000040001002000010109000101000501000100010109000000020001010005010001")), 158: ?line IOR2 = ?match({'IOP_IOR',_,_}, corba:string_to_object("IOR:000303030000000d49444c3a746573743a312e30000303030000000100000000000000e0000102010000000a3132372e302e302e31009d5f00000034abacab3131303432343836383731005f526f6f74504f410049494f505f43534976325f504f410000cafebabe3e23165700000000000000020000002100000054000102020000000100000202000000220000000800030303000000000000000000000000000000000400000000000000000000020000000806066781020101010000000b06092a864886f712010202010000000f000000010000002c0003030300010001000000040001002000010109000101000501000100010109000000020001010005010001")), 159: ?line IOR3 = ?match({'IOP_IOR',_,_}, corba:string_to_object("IOR:000303030000000d49444c3a746573743a312e3000030303000000010000000000000108000102010000000a3132372e302e302e31009d6100000037abacab3131303432343836383731005f526f6f74504f410049494f505f43534976325f55505f504f410000cafebabe3e231657000000000100000002000000210000007800010202000000010040020200000022000000080003030300000000004000400000000806066781020101010000001b0401000806066781020101010000000b40616469726f6e2e636f6d010400000000000000000000020000000806066781020101010000000b06092a864886f712010202010000000f000000010000002c0003030300010001000000040001002000010109000101000501000100010109000000020001010005010001")), 160: ?line IOR4 = ?match({'IOP_IOR',_,_}, corba:string_to_object("IOR:000303030000000d49444c3a746573743a312e3000030303000000010000000000000080000102010000000a3132372e302e302e31009d5d0000002eabacab3131303432343836383731005f526f6f74504f410049494f505f504f410000cafebabe3e23165700000000020200000001000000010000002c0003030300010001000000040001002000010109000101000501000100010109000000020001010005010001")), 161: ?line IOR5 = ?match({'IOP_IOR',_,_}, corba:string_to_object("IOR:000303030000000d49444c3a746573743a312e30000303030000000100000000000000fc000102010000000a3132372e302e302e3100000000000033abacab3131303432343836383731005f526f6f74504f4100544c535f43534976325f504f410000cafebabe3e231657000000000100000002000000210000007000010202000000010006020200000024000000220001006600060202000000010000000f3132382e3233302e3230382e353500019d6000000000020200000000000000000400000000000000000000020000000806066781020101010000000b06092a864886f712010202010000000f000000010000002c0003030300010001000000040001002000010109000101000501000100010109000000020001010005010001")), 162: ?line IOR6 = ?match({'IOP_IOR',_,_}, corba:string_to_object("IOR:000303030000000d49444c3a746573743a312e3000030303000000010000000000000124000102010000000a3132372e302e302e3100000000000036abacab3131303432343836383731005f526f6f74504f4100544c535f43534976325f55505f504f410000cafebabe3e23165700000000020200000002000000210000009400010202000000010046020200000024000000220001006600060202000000010000000f3132382e3233302e3230382e353500019d620040004002020000000806066781020101010000001b0401000806066781020101010000000b40616469726f6e2e636f6d010400000000000000000000020000000806066781020101010000000b06092a864886f712010202010000000f000000010000002c0003030300010001000000040001002000010109000101000501000100010109000000020001010005010001")), 163: ?line IOR7 = ?match({'IOP_IOR',_,_}, corba:string_to_object("IOR:000303030000000d49444c3a746573743a312e3000030303000000010000000000000090000102010000000a3132372e302e302e310000000000002dabacab3131303432343836383731005f526f6f74504f4100544c535f504f410000cafebabe3e231657000000000303030000000200000014000000080001006600069d5e000000010000002c0003030300010001000000040001002000010109000101000501000100010109000000020001010005010001")), 164: ?line IOR1 = corba:string_to_object(corba:object_to_string(IOR1)), 165: ?line IOR2 = corba:string_to_object(corba:object_to_string(IOR2)), 166: ?line IOR3 = corba:string_to_object(corba:object_to_string(IOR3)), 167: ?line IOR4 = corba:string_to_object(corba:object_to_string(IOR4)), 168: ?line IOR5 = corba:string_to_object(corba:object_to_string(IOR5)), 169: ?line IOR6 = corba:string_to_object(corba:object_to_string(IOR6)), 170: ?line IOR7 = corba:string_to_object(corba:object_to_string(IOR7)), 171: ?line ?match(ok, corba:print_object(IOR1)), 172: ?line ?match(ok, corba:print_object(IOR2)), 173: ?line ?match(ok, corba:print_object(IOR3)), 174: ?line ?match(ok, corba:print_object(IOR4)), 175: ?line ?match(ok, corba:print_object(IOR5)), 176: ?line ?match(ok, corba:print_object(IOR6)), 177: ?line ?match(ok, corba:print_object(IOR7)), 178: ?line ?match(ok, corba:print_object("IOR:000303030000000d49444c3a746573743a312e300003030300000002000000000000003000010001000000136d792e686f73742e65726c616e672e6f72670001801a02020000000c424f410a00000a0000070a010000000100000024000303030000000100000001000000140003030300010001000000000001010900000000")), 179: [IP] = ?match([_], orber:host()), 180: ?match(#'IOP_IOR'{profiles=[#'IOP_TaggedProfile' 181: {tag=?TAG_INTERNET_IOP, 182: profile_data=#'IIOP_ProfileBody_1_1' 183: {host = IP}}]}, 184: corba:string_to_object(corba:object_to_string(NS))), 185: ?match(#'IOP_IOR'{profiles=[#'IOP_TaggedProfile' 186: {tag=?TAG_INTERNET_IOP, 187: profile_data=#'IIOP_ProfileBody_1_1' 188: {host = "127.0.0.1"}}]}, 189: corba:string_to_object(corba:object_to_string(NS, ["127.0.0.1"]))), 190: ?match(#'IOP_IOR'{profiles=[#'IOP_TaggedProfile' 191: {tag=?TAG_INTERNET_IOP, 192: profile_data=#'IIOP_ProfileBody_1_1' 193: {host = "127.0.0.1", port = 5468}}]}, 194: corba:string_to_object(corba:object_to_string(NS, ["127.0.0.1"], 195: 5468))), 196: ok. 197: 198: %%----------------------------------------------------------------- 199: %% API tests for interface BOA 200: %%----------------------------------------------------------------- 201: boa_api(doc) -> ["BOA API tests", ""]; 202: boa_api(suite) -> []; 203: boa_api(_) -> 204: ok. 205: 206: %%----------------------------------------------------------------- 207: %% API tests for interface OBJECT 208: %%----------------------------------------------------------------- 209: object_api(doc) -> ["Object API tests", ""]; 210: object_api(suite) -> []; 211: object_api(_) -> 212: ?line oe_orber_test_server:oe_register(), 213: ?line EC = orber_test_server:oe_create(), 214: ?line NS = corba:resolve_initial_references("NameService"), 215: %% testing corba_object:is_a(Obj, IFRID) locally. 216: ?line orber_test_lib:corba_object_tests(EC, NS), 217: 218: ?line ?match(false, corba_object:non_existent(NS)), 219: 220: ?line corba:dispose(EC), 221: ?line oe_orber_test_server:oe_unregister(), 222: ok. 223: 224: %%----------------------------------------------------------------- 225: %% API tests for orbers main module 226: %%----------------------------------------------------------------- 227: orber_api(doc) -> ["orber API tests", ""]; 228: orber_api(suite) -> []; 229: orber_api(_) -> 230: ?line ok = orber:uninstall(), 231: ?line orber:install([node()]), 232: ?line application:start(orber), 233: ?line NodeList = orber:orber_nodes(), 234: ?line NL = node(), 235: ?line [NL] = NodeList, 236: ok. 237: 238: %%----------------------------------------------------------------- 239: %% API tests for exception mapping 240: %%----------------------------------------------------------------- 241: exception_info_api(doc) -> ["orber API tests", ""]; 242: exception_info_api(suite) -> []; 243: exception_info_api(_) -> 244: ?line {ok, S1} = orber:exception_info({'EXCEPTION',{'MARSHAL',[],1163001858,'COMPLETED_NO'}}), 245: ?line {ok, S2} = orber:exception_info({'EXCEPTION',{'MARSHAL',[],1330446337,'COMPLETED_NO'}}), 246: ?line {ok, S3} = orber:exception_info({'EXCEPTION',{'MARSHAL',[],1398079490,'COMPLETED_NO'}}), 247: ?line {ok, S4} = orber:exception_info({'EXCEPTION',{'MARSHAL',[],1347813377,'COMPLETED_NO'}}), 248: ?line {ok, S5} = orber:exception_info({'EXCEPTION', {'CosNaming_NamingContext_InvalidName',"IDL:omg.org/CosNaming/NamingContext/InvalidName:1.0"}}), 249: ?line error_logger:info_msg("~s", [S1]), 250: ?line error_logger:info_msg("~s", [S2]), 251: ?line error_logger:info_msg("~s", [S3]), 252: ?line error_logger:info_msg("~s", [S4]), 253: ?line error_logger:info_msg("~s", [S5]), 254: ok. 255: 256: %%----------------------------------------------------------------- 257: %% API tests for orbers pseudo objects. 258: %%----------------------------------------------------------------- 259: orber_pseudo_objects(doc) -> ["orber_pseudo_objects API tests", ""]; 260: orber_pseudo_objects(suite) -> []; 261: orber_pseudo_objects(_) -> 262: ?line oe_orber_test_server:oe_register(), 263: Obj1=(catch orber_test_server:oe_create(state,[{pseudo,true}, 264: {local_typecheck, true}])), 265: ?line ?match({_,pseudo,orber_test_server_impl, _,_, _}, Obj1), 266: Obj2=(catch orber_test_server:oe_create([],[{pseudo, truce}])), 267: ?line ?match({'EXCEPTION',{'BAD_PARAM',[],_,'COMPLETED_NO'}}, Obj2), 268: spawn(?MODULE, pseudo_calls, [20, Obj1]), 269: ?line ?match({ok, 10000}, orber_test_server:pseudo_call_delay(Obj1, 10000)), 270: spawn(?MODULE, pseudo_casts, [20, Obj1]), 271: ?line ?match(ok, orber_test_server:pseudo_cast_delay(Obj1, 10000)), 272: 273: ?line ?match('object_here', corba:locate(Obj1)), 274: 275: ?line NS = corba:resolve_initial_references("NameService"), 276: 277: ?line orber_test_lib:corba_object_tests(Obj1, NS), 278: 279: ?line ?match("IDL:omg.org/orber_test/server:1.0",orber_test_server:typeID()), 280: 281: %% Test if exceptions are handled properly. 282: ?line ?match({'EXCEPTION',{'BAD_QOS',_,_,_}}, 283: orber_test_server:pseudo_call_raise_exc(Obj1, 1)), 284: ?line ?match({'EXCEPTION',{'BAD_QOS',_,_,_}}, 285: orber_test_server:pseudo_call_raise_exc(Obj1, 2)), 286: 287: %% Test if exit is handled properly. 288: ?line ?match({'EXCEPTION',{'TRANSIENT',_,_,_}}, 289: orber_test_server:stop_brutal(Obj1)), 290: 291: orber_test_lib:test_coding(Obj1, true), 292: 293: %% possible to use subobject key? 294: ?line ?match(state, binary_to_term(corba:get_subobject_key(Obj1))), 295: 296: ?line ?match({'EXCEPTION',{'INV_OBJREF',[],_,'COMPLETED_NO'}}, 297: corba:get_pid(Obj1)), 298: ?line ?match(false, corba_object:non_existent(Obj1)), 299: 300: ?line ?match(ok, corba:dispose(Obj1)), 301: 302: ?line ?match(false, corba_object:non_existent(Obj1)), 303: 304: %% Try if it's possible to stringify and recover the object reference. 305: IOR_string = (catch corba:object_to_string(Obj1)), 306: Obj3 =(catch corba:string_to_object(IOR_string)), 307: ?line ?match(IOR_string, corba:object_to_string(Obj3)), 308: 309: Obj4=(catch orber_test_server:oe_create(undefined,[{pseudo,true}])), 310: ?line ?match(ok, corba:dispose(Obj4)), 311: ?line oe_orber_test_server:oe_unregister(), 312: ok. 313: 314: %%----------------------------------------------------------------- 315: %% API tests for orbers objectkeys server. 316: %%----------------------------------------------------------------- 317: orber_objectkeys_api(doc) -> ["orber_objectkeys API tests", ""]; 318: orber_objectkeys_api(suite) -> []; 319: orber_objectkeys_api(_) -> 320: Obj0=(catch orber_test_server:oe_create([], [{sup_child, true}])), 321: Obj1=(catch orber_test_server:oe_create([], [{persistent, true}, 322: {regname, {local,obj1}}])), 323: Obj2=(catch orber_test_server:oe_create([], [{persistent, true}, 324: {regname, {global,{obj2, 12345}}}])), 325: 326: %% Obj0 is supposed to be a child started by a supervisor (r6) which 327: %% handles not only {ok, Pid} but also {ok,Pid, Returnvalue}. In our 328: %% case the Returnvalue is an ObjectRef. 329: ?line ?match({ok,_,{_,key,_, _,_, _}}, Obj0), 330: {ok,_,Obj0Ref} = Obj0, 331: corba:dispose(Obj0Ref), 332: 333: %% Only 'global' servers are at the moment allowed to be persistent. 334: ?line ?match({'EXCEPTION',{'BAD_PARAM',[],_,'COMPLETED_NO'}}, Obj1), 335: 336: %% We created a persistent object successfully. 337: ?line ?match({_,key,_,_,_, _}, Obj2), 338: 339: %% Get key and Pid 340: {_,_,Key,_,_, _} = Obj2, 341: PID=(catch orber_objectkeys:get_pid(Key)), 342: 343: %% Use the two different ways to look up if the server is persistent. 344: ?line ?match(true, orber_objectkeys:is_persistent(Key)), 345: ?line ?match(true, orber_objectkeys:is_persistent(PID)), 346: 347: %% Create servers using every possible way. 348: O1=(catch orber_test_server:oe_create()), 349: O2=(catch orber_test_server:oe_create_link()), 350: O3=(catch orber_test_server:oe_create([])), 351: O4=(catch orber_test_server:oe_create_link([])), 352: %% NOTE!!! Next four lines requires that we still support RegName instead of 353: %% only OptionList as the second argument to oe_create*/2. Remove these when that 354: %% is no longer the case. 355: O5=(catch orber_test_server:oe_create([], {'local', o5})), 356: O6=(catch orber_test_server:oe_create([], {'global', {o6, obj}})), 357: O7=(catch orber_test_server:oe_create_link([], {'local', o7})), 358: O8=(catch orber_test_server:oe_create_link([], {'global', {o8, obj}})), 359: 360: %% Test if all the object references are correct. 361: ?line ?match({_,key,_,_,_, _}, O1), 362: ?line ?match({_,key,_,_,_, _}, O2), 363: ?line ?match({_,key,_,_,_, _}, O3), 364: ?line ?match({_,key,_,_,_, _}, O4), 365: ?line ?match({_, registered, o5, _,_, _}, O5), 366: ?line ?match({_,key,_,_,_, _}, O6), 367: ?line ?match({_, registered, o7, _,_, _}, O7), 368: ?line ?match({_,key,_,_,_, _}, O8), 369: 370: %% Test if persistent. 371: {_,_,Key1,_,_, _} = O1, 372: PID1=(catch orber_objectkeys:get_pid(Key1)), 373: ?line ?match(false, orber_objectkeys:is_persistent(Key1)), 374: ?line ?match(false, orber_objectkeys:is_persistent(PID1)), 375: 376: %% all the servers are alive(?!). 377: ?line ?match(false, corba_object:non_existent(O1)), 378: ?line ?match(false, corba_object:non_existent(O2)), 379: ?line ?match(false, corba_object:non_existent(O3)), 380: ?line ?match(false, corba_object:non_existent(O4)), 381: ?line ?match(false, corba_object:non_existent(O5)), 382: ?line ?match(false, corba_object:non_existent(O6)), 383: ?line ?match(false, corba_object:non_existent(O7)), 384: ?line ?match(false, corba_object:non_existent(O8)), 385: ?line ?match(false, corba_object:non_existent(Obj2)), 386: 387: %% Does locate work? 388: ?line ?match('object_here', corba:locate(O1)), 389: ?line ?match('object_here', corba:locate(O2)), 390: ?line ?match('object_here', corba:locate(O3)), 391: ?line ?match('object_here', corba:locate(O4)), 392: ?line ?match('object_here', corba:locate(O5)), 393: ?line ?match('object_here', corba:locate(O6)), 394: ?line ?match('object_here', corba:locate(O7)), 395: ?line ?match('object_here', corba:locate(O8)), 396: ?line ?match('object_here', corba:locate(Obj2)), 397: 398: %% Terminate all servers with reason 'normal'. 399: catch corba:dispose(O1), 400: catch corba:dispose(O2), 401: catch corba:dispose(O3), 402: catch corba:dispose(O4), 403: catch corba:dispose(O5), 404: catch corba:dispose(O6), 405: catch corba:dispose(O7), 406: catch corba:dispose(O8), 407: catch corba:dispose(Obj2), 408: 409: 410: %% To make sure that orber_objectkeys-server is able to 411: %% clean up we wait. 412: timer:sleep(2000), 413: 414: %% all the servers are dead(?!). If one of these test-cases 415: %% fails the only error can be that we didn't sleep long enough, i.e., 416: %% try a longer timeout. If still fails something is wrong. 417: ?line ?match(true, corba_object:non_existent(O1)), 418: ?line ?match(true, corba_object:non_existent(O2)), 419: ?line ?match(true, corba_object:non_existent(O3)), 420: ?line ?match(true, corba_object:non_existent(O4)), 421: ?line ?match(true, corba_object:non_existent(O5)), 422: ?line ?match(true, corba_object:non_existent(O6)), 423: ?line ?match(true, corba_object:non_existent(O7)), 424: ?line ?match(true, corba_object:non_existent(O8)), 425: ?line ?match(true, corba_object:non_existent(Obj2)), 426: 427: %% Create a new persistent server. 428: Obj3=(catch orber_test_server:oe_create([], 429: [{persistent, true}, 430: {regname, {global,{obj2, 12345}}}])), 431: 432: %% OK?! 433: ?line ?match({_,key,_,_,_, _}, Obj3), 434: 435: %% Try to create a server with the same name (naturally it fails). 436: ?line ?match({'EXCEPTION',{'INTERNAL',[],_,'COMPLETED_NO'}}, 437: orber_test_server:oe_create([], 438: [{persistent, true}, 439: {regname, {global,{obj2, 12345}}}])), 440: %% Try to remove all 'dead' servers. No server should be removed. 441: orber_objectkeys:gc(0), 442: 443: %% Kill object brutal, i.e., not with reason 'normal' or 'shutdown'. 444: P3 = corba:get_pid(Obj3), 445: exit(P3, kill), 446: 447: {_,_,Key3,_,_, _} = Obj3, 448: 449: %% Give time to clean up. 450: timer:sleep(2000), 451: ?line ?match({'EXCEPTION',{'TRANSIENT',[],_,'COMPLETED_NO'}}, 452: gen_server:call(orber_objkeyserver, 453: {get_pid, Key3}, 454: infinity)), 455: 456: ?line ?match(false,corba_object:non_existent(Obj3)), 457: 458: %% Run gc wit a "huge" time-limit. Will not erase the dead object. 459: orber_objectkeys:gc(10000), 460: ?line ?match(false,corba_object:non_existent(Obj3)), 461: 462: %% Run gc with minimum time-limit. Will erase the dead object. 463: orber_objectkeys:gc(0), 464: ?line ?match(true,corba_object:non_existent(Obj3)), 465: 466: %% Create a new persistent server. 467: Obj4=(catch orber_test_server:oe_create([], 468: [{persistent, true}, 469: {regname, {global,{obj2, 12345}}}])), 470: 471: %% OK?! 472: ?match({_,key,_,_,_, _}, Obj4), 473: %% Kill object brutal, i.e., not with reason 'normal' or 'shutdown'. 474: P4 = corba:get_pid(Obj4), 475: exit(P4, kill), 476: 477: %% Give time to clean up. 478: timer:sleep(2000), 479: % ?line ?match({'EXCEPTION',{'COMM_FAILURE',[],0,'COMPLETED_NO'}}, 480: ?line ?match({error, _}, 481: corba:get_pid(Obj4)), 482: 483: ?line ?match(false,corba_object:non_existent(Obj4)), 484: 485: %% Restart the object. 486: Obj5=(catch orber_test_server:oe_create([], 487: [{persistent, true}, 488: {regname, {global,{obj2, 12345}}}])), 489: %% OK?! 490: ?line ?match({_,key,_,_,_, _}, Obj5), 491: 492: %% Run gc with minimum time-limit. 493: orber_objectkeys:gc(0), 494: ?line ?match(false,corba_object:non_existent(Obj5)), 495: corba:dispose(Obj5), 496: ok. 497: 498: 499: %%----------------------------------------------------------------- 500: %% API tests for callback functions 501: %%----------------------------------------------------------------- 502: -define(DO_EXIT_FLAG, 0). 503: -define(NO_EXIT_FLAG, 16#10). 504: 505: -define(DO_EXIT, {is, 0}). 506: -define(NO_EXIT, {is, 16#10}). 507: 508: 509: 510: callback_ok_api(doc) -> ["Successful callbak API tests", ""]; 511: callback_ok_api(suite) -> []; 512: callback_ok_api(_) -> 513: %% Init 514: ?line ?match({ok, {?DO_EXIT, state}}, corba:handle_init(?MODULE, {?DO_EXIT_FLAG, state})), 515: %% Terminate 516: ?line ?match(ok, corba:handle_terminate(?MODULE, "reason", {?DO_EXIT, state})), 517: %% Handle_call 518: ?line ?match({reply,ok,{?DO_EXIT,state}}, 519: corba:handle_call(?MODULE, foo, [], 520: {?DO_EXIT, state}, [], false, false)), 521: %% Handle_cast 522: ?line ?match({noreply, {?DO_EXIT,state}}, 523: corba:handle_cast(?MODULE, foo_1w, [], 524: {?DO_EXIT, state}, [], false)), 525: %% Handle_call precond/postcond 526: ?line ?match({reply, ok, {?DO_EXIT, state}}, 527: corba:handle_call(?MODULE, foo, [], 528: {?DO_EXIT, state}, [], false, false, {?MODULE, precond}, 529: {?MODULE, postcond}, ?MODULE)), 530: %% Handle_cast precond/postcond 531: ?line ?match({noreply, {?DO_EXIT, state}}, 532: corba:handle_cast(?MODULE, foo_1w, [], 533: {?DO_EXIT, state}, [], false, {?MODULE, precond}, 534: {?MODULE, postcond}, ?MODULE)), 535: %% Handle_info 536: ?line ?match({noreply, {?DO_EXIT, state}}, 537: corba:handle_info(?MODULE, "info", {?DO_EXIT, state})), 538: ok. 539: 540: callback_arity_api(doc) -> ["callbak arity API tests", ""]; 541: callback_arity_api(suite) -> []; 542: callback_arity_api(_) -> 543: %% Handle_call - stay-alive == false 544: ?line ?match({'EXIT', {undef,_}}, 545: corba:handle_call(?MODULE, foo, [to, many, arguments], 546: {?DO_EXIT, state}, [], false, false)), 547: %% Handle_call - stay-alive == true 548: ?line ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}}, _}, 549: corba:handle_call(?MODULE, foo, [to, many, arguments], 550: {?NO_EXIT, state}, [], false, false)), 551: %% Handle_call - stay-alive == false 552: ?line ?match({'EXIT', _}, 553: corba:handle_call(?MODULE, foo, [], 554: {?DO_EXIT, arity}, [], false, false)), 555: %% Handle_call - stay-alive == true 556: ?line ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}}, _}, 557: corba:handle_call(?MODULE, foo, [], 558: {?NO_EXIT, arity}, [], false, false)), 559: %% Handle_cast - stay-alive == false 560: ?line ?match({'EXIT', {undef,_}}, 561: corba:handle_cast(?MODULE, foo_1w, [to, many, arguments], 562: {?DO_EXIT, state}, [], false)), 563: %% Handle_cast - stay-alive == true 564: ?line ?match({noreply, {?NO_EXIT, state}}, 565: corba:handle_cast(?MODULE, foo_1w, [to, many, arguments], 566: {?NO_EXIT, state}, [], false)), 567: %% Handle_cast - stay-alive == false 568: ?line ?match({'EXIT', _}, 569: corba:handle_cast(?MODULE, foo_1w, [], 570: {?DO_EXIT, arity}, [], false)), 571: %% Handle_cast - stay-alive == true 572: ?line ?match({noreply, {?NO_EXIT, arity}}, 573: corba:handle_cast(?MODULE, foo_1w, [], 574: {?NO_EXIT, arity}, [], false)), 575: %% Handle_info - stay-alive == false 576: ?line ?match({'EXIT', _}, 577: corba:handle_info(?MODULE, "info", {?DO_EXIT, arity})), 578: 579: %% Handle_info - stay-alive == true 580: ?line ?match({noreply, {?NO_EXIT, arity}}, 581: corba:handle_info(?MODULE, "info", {?NO_EXIT, arity})), 582: ok. 583: 584: callback_module_api(doc) -> ["Module callbak API tests", ""]; 585: callback_module_api(suite) -> []; 586: callback_module_api(_) -> 587: %% Handle_call - stay-alive == false 588: ?line ?match({'EXIT', {undef,_}}, 589: corba:handle_call(wrong_mod, foo, [], 590: {?DO_EXIT, state}, [], false, false)), 591: %% Handle_call - stay-alive == true 592: ?line ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}}, _}, 593: corba:handle_call(wrong_mod, foo, [], 594: {?NO_EXIT, state}, [], false, false)), 595: %% Handle_cast - stay-alive == false 596: ?line ?match({'EXIT', {undef,_}}, 597: corba:handle_cast(wrong_mod, foo_1w, [], 598: {?DO_EXIT, state}, [], false)), 599: %% Handle_cast - stay-alive == true 600: ?line ?match({noreply, {?NO_EXIT, state}}, 601: corba:handle_cast(wrong_mod, foo_1w, [], 602: {?NO_EXIT, state}, [], false)), 603: %% Handle_info - stay-alive == false. 604: ?line ?match({'EXIT', _}, 605: corba:handle_info(wrong_mod, "info", {?DO_EXIT, state})), 606: 607: %% Handle_info - stay-alive == true. 608: ?line ?match({noreply, {?NO_EXIT, state}}, 609: corba:handle_info(wrong_mod, "info", {?NO_EXIT, state})), 610: ok. 611: 612: callback_function_api(doc) -> ["Function callbak API tests", ""]; 613: callback_function_api(suite) -> []; 614: callback_function_api(_) -> 615: %% Handle_call - stay-alive == false 616: ?line ?match({'EXIT', {undef,_}}, 617: corba:handle_call(?MODULE, bad_function, [], 618: {?DO_EXIT, state}, [], false, false)), 619: %% Handle_call - stay-alive == true 620: ?line ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}}, _}, 621: corba:handle_call(?MODULE, bad_function, [], 622: {?NO_EXIT, state}, [], false, false)), 623: %% Handle_cast - stay-alive == false 624: ?line ?match({'EXIT', {undef,_}}, 625: corba:handle_cast(?MODULE, bad_function, [], 626: {?DO_EXIT, state}, [], false)), 627: %% Handle_cast - stay-alive == true 628: ?line ?match({noreply, {?NO_EXIT, state}}, 629: corba:handle_cast(?MODULE, bad_function, [], 630: {?NO_EXIT, state}, [], false)), 631: %% Handle_info - stay-alive == false. Note, we cannot use ?MODULE here. 632: ?line ?match({'EXIT', _}, 633: corba:handle_info(corba, "info", {?DO_EXIT, state})), 634: 635: %% Handle_info - stay-alive == true. Note, we cannot use ?MODULE here. 636: ?line ?match({noreply, {?NO_EXIT, state}}, 637: corba:handle_info(corba, "info", {?NO_EXIT, state})), 638: ok. 639: 640: callback_precond_api(doc) -> ["Precond callbak API tests", ""]; 641: callback_precond_api(suite) -> []; 642: callback_precond_api(_) -> 643: %% Handle_call - stay-alive == false 644: ?line ?match({'EXIT', _}, 645: corba:handle_call(?MODULE, foo, [], 646: {?DO_EXIT, state}, [], false, false, {wrong_mod, precond}, 647: {?MODULE, postcond}, ?MODULE)), 648: %% Handle_call - stay-alive == false 649: ?line ?match({'EXIT', _}, 650: corba:handle_call(?MODULE, foo, [], 651: {?DO_EXIT, state}, [], false, false, {?MODULE, bad_precond}, 652: {?MODULE, postcond}, ?MODULE)), 653: %% Handle_call - stay-alive == true 654: ?line ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}},_}, 655: corba:handle_call(?MODULE, foo, [], 656: {?NO_EXIT, state}, [], false, false, {wrong_mod, precond}, 657: {?MODULE, postcond}, ?MODULE)), 658: %% Handle_call - stay-alive == true 659: ?line ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}},_}, 660: corba:handle_call(?MODULE, foo, [], 661: {?NO_EXIT, state}, [], false, false, {?MODULE, bad_precond}, 662: {?MODULE, postcond}, ?MODULE)), 663: %% Handle_cast - stay-alive == false 664: ?line ?match({'EXIT', _}, 665: corba:handle_cast(?MODULE, foo_1w, [], 666: {?DO_EXIT, state}, [], false, {wrong_mod, precond}, 667: {?MODULE, postcond}, ?MODULE)), 668: %% Handle_cast - stay-alive == false 669: ?line ?match({'EXIT', _}, 670: corba:handle_cast(?MODULE, foo_1w, [], 671: {?DO_EXIT, state}, [], false, {?MODULE, bad_precond}, 672: {?MODULE, postcond}, ?MODULE)), 673: %% Handle_cast - stay-alive == true 674: ?line ?match({noreply, {?NO_EXIT, state}}, 675: corba:handle_cast(?MODULE, foo_1w, [], 676: {?NO_EXIT, state}, [], false, {wrong_mod, precond}, 677: {?MODULE, postcond}, ?MODULE)), 678: %% Handle_cast - stay-alive == true 679: ?line ?match({noreply, {?NO_EXIT, state}}, 680: corba:handle_cast(?MODULE, foo_1w, [], 681: {?NO_EXIT, state}, [], false, {?MODULE, bad_precond}, 682: {?MODULE, postcond}, ?MODULE)), 683: ok. 684: 685: 686: callback_postcond_api(doc) -> ["Postcond callbak API tests", ""]; 687: callback_postcond_api(suite) -> []; 688: callback_postcond_api(_) -> 689: %% Handle_call - stay-alive == false 690: ?line ?match({'EXIT', _}, 691: corba:handle_call(?MODULE, foo, [], 692: {?DO_EXIT, state}, [], false, false, {?MODULE, precond}, 693: {wrong_mod, postcond}, ?MODULE)), 694: %% Handle_call - stay-alive == false 695: ?line ?match({'EXIT', _}, 696: corba:handle_call(?MODULE, foo, [], 697: {?DO_EXIT, state}, [], false, false, {?MODULE, precond}, 698: {?MODULE, bad_postcond}, ?MODULE)), 699: %% Handle_call - stay-alive == true 700: ?line ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}},_}, 701: corba:handle_call(?MODULE, foo, [], 702: {?NO_EXIT, state}, [], false, false, {?MODULE, precond}, 703: {wrong_mod, postcond}, ?MODULE)), 704: %% Handle_call - stay-alive == true 705: ?line ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}},_}, 706: corba:handle_call(?MODULE, foo, [], 707: {?NO_EXIT, state}, [], false, false, {?MODULE, precond}, 708: {?MODULE, bad_postcond}, ?MODULE)), 709: %% Handle_cast - stay-alive == false 710: ?line ?match({'EXIT', _}, 711: corba:handle_cast(?MODULE, foo_1w, [], 712: {?DO_EXIT, state}, [], false, {?MODULE, precond}, 713: {wrong_mod, postcond}, ?MODULE)), 714: %% Handle_cast - stay-alive == false 715: ?line ?match({'EXIT', _}, 716: corba:handle_cast(?MODULE, foo_1w, [], 717: {?DO_EXIT, state}, [], false, {?MODULE, precond}, 718: {?MODULE, bad_postcond}, ?MODULE)), 719: %% Handle_cast - stay-alive == true 720: ?line ?match({noreply, {?NO_EXIT, state}}, 721: corba:handle_cast(?MODULE, foo_1w, [], 722: {?NO_EXIT, state}, [], false, {?MODULE, precond}, 723: {wrong_mod, postcond}, ?MODULE)), 724: %% Handle_cast - stay-alive == true 725: ?line ?match({noreply, {?NO_EXIT, state}}, 726: corba:handle_cast(?MODULE, foo_1w, [], 727: {?NO_EXIT, state}, [], false, {?MODULE, precond}, 728: {?MODULE, bad_postcond}, ?MODULE)), 729: ok. 730: 731: 732: callback_exit_api(doc) -> ["Callbak exit API tests", ""]; 733: callback_exit_api(suite) -> []; 734: callback_exit_api(_) -> 735: %% Handle_call - stay-alive == false 736: ?line ?match({'EXIT', _}, 737: corba:handle_call(?MODULE, foo, [], 738: {?DO_EXIT, exit}, [], false, false)), 739: %% Handle_call - stay-alive == true 740: ?line ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}}, _}, 741: corba:handle_call(?MODULE, foo, [], 742: {?NO_EXIT, exit}, [], false, false)), 743: %% Handle_cast - stay-alive == false 744: ?line ?match({'EXIT', _}, 745: corba:handle_cast(?MODULE, foo_1w, [], 746: {?DO_EXIT, exit}, [], false)), 747: %% Handle_cast - stay-alive == true 748: ?line ?match({noreply, {?NO_EXIT, exit}}, 749: corba:handle_cast(?MODULE, foo_1w, [], 750: {?NO_EXIT, exit}, [], false)), 751: %% Handle_info - stay-alive == false 752: ?line ?match({'EXIT', _}, 753: corba:handle_info(?MODULE, "info", {?DO_EXIT, exit})), 754: 755: %% Handle_info - stay-alive == true 756: ?line ?match({noreply, {?NO_EXIT, exit}}, 757: corba:handle_info(?MODULE, "info", {?NO_EXIT, exit})), 758: ok. 759: 760: 761: callback_badarith_api(doc) -> ["callbak badarith API tests", ""]; 762: callback_badarith_api(suite) -> []; 763: callback_badarith_api(_) -> 764: %% Handle_call - stay-alive == false 765: ?line ?match({'EXIT', _}, 766: corba:handle_call(?MODULE, foo, [], 767: {?DO_EXIT, badarith}, [], false, false)), 768: %% Handle_call - stay-alive == true 769: ?line ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}},_}, 770: corba:handle_call(?MODULE, foo, [], 771: {?NO_EXIT, badarith}, [], false, false)), 772: %% Handle_cast - stay-alive == false 773: ?line ?match({'EXIT', _}, 774: corba:handle_cast(?MODULE, foo_1w, [], 775: {?DO_EXIT, badarith}, [], false)), 776: %% Handle_cast - stay-alive == true 777: ?line ?match({noreply, {?NO_EXIT, badarith}}, 778: corba:handle_cast(?MODULE, foo_1w, [], 779: {?NO_EXIT, badarith}, [], false)), 780: %% Handle_info - stay-alive == false 781: ?line ?match({'EXIT', _}, 782: corba:handle_info(?MODULE, "info", {?DO_EXIT, badarith})), 783: 784: %% Handle_info - stay-alive == true 785: ?line ?match({noreply, {?NO_EXIT, badarith}}, 786: corba:handle_info(?MODULE, "info", {?NO_EXIT, badarith})), 787: ok. 788: 789: callback_case_clause_api(doc) -> ["callbak case_clause API tests", ""]; 790: callback_case_clause_api(suite) -> []; 791: callback_case_clause_api(_) -> 792: %% Handle_call - stay-alive == false 793: ?line ?match({'EXIT', _}, 794: corba:handle_call(?MODULE, foo, [], 795: {?DO_EXIT, case_clause}, [], false, false)), 796: %% Handle_call - stay-alive == true 797: ?line ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}}, _}, 798: corba:handle_call(?MODULE, foo, [], 799: {?NO_EXIT, case_clause}, [], false, false)), 800: %% Handle_cast - stay-alive == false 801: ?line ?match({'EXIT', _}, 802: corba:handle_cast(?MODULE, foo_1w, [], 803: {?DO_EXIT, case_clause}, [], false)), 804: %% Handle_cast - stay-alive == true 805: ?line ?match({noreply, {?NO_EXIT, case_clause}}, 806: corba:handle_cast(?MODULE, foo_1w, [], 807: {?NO_EXIT, case_clause}, [], false)), 808: %% Handle_info - stay-alive == false 809: ?line ?match({'EXIT', _}, 810: corba:handle_info(?MODULE, "info", {?DO_EXIT, case_clause})), 811: 812: %% Handle_info - stay-alive == true 813: ?line ?match({noreply, {?NO_EXIT, case_clause}}, 814: corba:handle_info(?MODULE, "info", {?NO_EXIT, case_clause})), 815: ok. 816: 817: callback_function_clause_api(doc) -> ["callbak function_clause API tests", ""]; 818: callback_function_clause_api(suite) -> []; 819: callback_function_clause_api(_) -> 820: %% Handle_call - stay-alive == false 821: ?line ?match({'EXIT', _}, 822: corba:handle_call(?MODULE, foo, [], 823: {?DO_EXIT, function_clause}, [], false, false)), 824: %% Handle_call - stay-alive == true 825: ?line ?match({reply, {'EXCEPTION', #'OBJ_ADAPTER'{}}, _}, 826: corba:handle_call(?MODULE, foo, [], 827: {?NO_EXIT, function_clause}, [], false, false)), 828: %% Handle_cast - stay-alive == false 829: ?line ?match({'EXIT', _}, 830: corba:handle_cast(?MODULE, foo_1w, [], 831: {?DO_EXIT, function_clause}, [], false)), 832: %% Handle_cast - stay-alive == true 833: ?line ?match({noreply, {?NO_EXIT, function_clause}}, 834: corba:handle_cast(?MODULE, foo_1w, [], 835: {?NO_EXIT, function_clause}, [], false)), 836: %% Handle_info - stay-alive == false 837: ?line ?match({'EXIT', _}, 838: corba:handle_info(?MODULE, "info", {?DO_EXIT, function_clause})), 839: %% Handle_info - stay-alive == true 840: ?line ?match({noreply, {?NO_EXIT, function_clause}}, 841: corba:handle_info(?MODULE, "info", {?NO_EXIT, function_clause})), 842: ok. 843: 844: %% Faked mandatory operations 845: init(State) -> 846: evaluate_state(State), 847: {ok, State}. 848: terminate(_Reason, State) -> 849: evaluate_state(State), 850: ok. 851: 852: code_change(_OldVsn, State, _Extra) -> 853: evaluate_state(State), 854: {ok, State}. 855: handle_call(_,_, State) -> 856: evaluate_state(State), 857: {noreply, State}. 858: handle_cast(_, State) -> 859: evaluate_state(State), 860: {noreply, State}. 861: handle_info(_Info, State) -> 862: evaluate_state(State), 863: {noreply, State}. 864: 865: foo(State) -> 866: evaluate_state(State), 867: {reply, ok, State}. 868: foo(State, _Arg) -> 869: evaluate_state(State), 870: {reply, ok, State}. 871: 872: foo_1w(State) -> 873: evaluate_state(State), 874: {noreply, State}. 875: foo_1w(State, _Arg) -> 876: evaluate_state(State), 877: {noreply, State}. 878: 879: precond(_Module, _Function, _Args) -> 880: ok. 881: 882: postcond(_Module, _Function, _Args, _Result) -> 883: ok. 884: 885: evaluate_state(exit) -> 886: exit("exit on purpose"); 887: evaluate_state(badarith) -> 888: 10 * atom; 889: evaluate_state(case_clause) -> 890: case 10 of 891: false -> 892: ok 893: end; 894: evaluate_state(module) -> 895: non_existing_module:bar(); 896: evaluate_state(function) -> 897: ?MODULE:non_existing_function(); 898: evaluate_state(arity) -> 899: ?MODULE:foo(to, many, arguments); 900: evaluate_state(function_clause) -> 901: evaluate_state(incorrect_state); 902: evaluate_state(state) -> 903: ok. 904: 905: %%----------------------------------------------------------------- 906: %% Local functions. 907: %%----------------------------------------------------------------- 908: 909: pseudo_calls(0, _) -> 910: ok; 911: pseudo_calls(Times, Obj) -> 912: orber_test_server:pseudo_call(Obj), 913: New = Times - 1, 914: pseudo_calls(New, Obj). 915: pseudo_casts(0, _) -> 916: ok; 917: pseudo_casts(Times, Obj) -> 918: orber_test_server:pseudo_cast(Obj), 919: New = Times - 1, 920: pseudo_casts(New, Obj).