1: %% @doc This suite tests both old ejabberd_commands module, which is slowly getting deprecated, 2: %% and the new mongoose_commands implementation. 3: -module(commands_backend_SUITE). 4: -compile([export_all, nowarn_export_all]). 5: 6: -include_lib("exml/include/exml.hrl"). 7: -include_lib("eunit/include/eunit.hrl"). 8: -include("ejabberd_commands.hrl"). 9: 10: -define(PORT, 5288). 11: -define(HOST, "localhost"). 12: -define(IP, {127,0,0,1}). 13: 14: %% Error messages 15: -define(ARGS_LEN_ERROR, <<"Bad parameters length.">>). 16: -define(ARGS_SPEC_ERROR, <<"Bad name of the parameter.">>). 17: -type method() :: string(). 18: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 19: %%%% suite configuration 20: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 21: 22: client_module() -> 23: mongoose_api_client. 24: 25: backend_module() -> 26: mongoose_api_admin. 27: 28: all() -> 29: [ 30: {group, simple_backend}, 31: {group, get_advanced_backend}, 32: {group, post_advanced_backend}, 33: {group, delete_advanced_backend}, 34: {group, simple_client} 35: ]. 36: 37: groups() -> 38: [ 39: {simple_backend, [sequence], 40: [ 41: get_simple, 42: post_simple, 43: delete_simple, 44: put_simple 45: ] 46: }, 47: {get_advanced_backend, [sequence], 48: [ 49: get_two_args, 50: get_wrong_path, 51: get_wrong_arg_number, 52: get_no_command, 53: get_wrong_arg_type 54: ] 55: }, 56: {post_advanced_backend, [sequence], 57: [ 58: post_simple_with_subcategory, 59: post_different_arg_order, 60: post_wrong_arg_number, 61: post_wrong_arg_name, 62: post_wrong_arg_type, 63: post_no_command 64: ] 65: }, 66: {delete_advanced_backend, [sequence], 67: [ 68: delete_wrong_arg_order, 69: delete_wrong_arg_types 70: ] 71: }, 72: {put_advanced_backend, [sequence], 73: [ 74: put_wrong_type, 75: put_wrong_param_type, 76: put_wrong_bind_type, 77: put_different_params_order, 78: put_wrong_binds_order, 79: put_too_less_params, 80: put_too_less_binds, 81: put_wrong_bind_name, 82: put_wrong_param_name 83: ] 84: }, 85: {simple_client, [sequence], 86: [ 87: get_simple_client, 88: get_two_args_client, 89: get_bad_auth, 90: post_simple_client, 91: put_simple_client, 92: delete_simple_client 93: ] 94: } 95: ]. 96: 97: setup(Module) -> 98: meck:unload(), 99: meck:new(supervisor, [unstick, passthrough, no_link]), 100: meck:new(gen_hook, []), 101: meck:new(ejabberd_auth, []), 102: %% you have to meck some stuff to get it working.... 103: meck:expect(gen_hook, add_handler, fun(_, _, _, _, _) -> ok end), 104: meck:expect(gen_hook, run_fold, fun(_, _, _, _) -> {ok, ok} end), 105: spawn(fun mc_holder/0), 106: meck:expect(supervisor, start_child, 107: fun(ejabberd_listeners, {_, {_, start_link, [_]}, transient, 108: infinity, worker, [_]}) -> {ok, self()}; 109: (A,B) -> meck:passthrough([A,B]) 110: end), 111: %% HTTP API config 112: Opts = [{num_acceptors, 10}, 113: {max_connections, 1024}, 114: {modules, [{"localhost", "/api", Module, []}]}], 115: ejabberd_cowboy:start_listener({?PORT, ?IP, tcp}, Opts). 116: 117: teardown() -> 118: cowboy:stop_listener(ejabberd_cowboy:ref({?PORT, ?IP, tcp})), 119: mongoose_commands:unregister(commands_new()), 120: meck:unload(ejabberd_auth), 121: meck:unload(gen_hook), 122: meck:unload(supervisor), 123: mc_holder_proc ! stop, 124: ok. 125: 126: init_per_suite(C) -> 127: application:ensure_all_started(cowboy), 128: application:ensure_all_started(jid), 129: application:ensure_all_started(fusco), 130: ok = mnesia:start(), 131: C. 132: 133: end_per_suite(C) -> 134: stopped = mnesia:stop(), 135: mnesia:delete_schema([node()]), 136: application:stop(fusco), 137: application:stop(cowboy), 138: C. 139: 140: init_per_group(_, C) -> 141: C. 142: 143: end_per_group(_, C) -> 144: C. 145: 146: init_per_testcase(_, C) -> 147: C. 148: 149: end_per_testcase(_, C) -> 150: C. 151: 152: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 153: %%%% Backend side tests 154: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 155: 156: get_simple(_Config) -> 157: Arg = {arg1, <<"bob@localhost">>}, 158: Base = "/api/users", 159: ExpectedBody = get_simple_command(element(2, Arg)), 160: {ok, Response} = request(create_path_with_binds(Base, [Arg]), "GET", admin), 161: check_status_code(Response, 200), 162: check_response_body(Response, ExpectedBody). 163: 164: delete_simple(_Config) -> 165: Arg1 = {arg1, <<"ala_ma_kota">>}, 166: Arg2 = {arg2, 2}, 167: Base = "/api/music", 168: {ok, Response} = request(create_path_with_binds(Base, [Arg1, Arg2]), "DELETE", admin), 169: check_status_code(Response, 204). 170: 171: post_simple(_Config) -> 172: Arg1 = {arg1, 10}, 173: Arg2 = {arg2, 2}, 174: Args = [Arg1, Arg2], 175: Path = <<"/api/weather">>, 176: Result = binary_to_list(post_simple_command(element(2, Arg1), element(2, Arg2))), 177: {ok, Response} = request(Path, "POST", Args, admin), 178: check_status_code(Response, 201), 179: check_location_header(Response, list_to_binary(build_path_prefix()++"/api/weather/" ++ Result)). 180: 181: post_simple_with_subcategory(_Config) -> 182: Arg1 = {arg1, 10}, 183: Arg2 = {arg2, 2}, 184: Args = [Arg2], 185: Path = <<"/api/weather/10/subcategory">>, 186: Result = binary_to_list(post_simple_command(element(2, Arg1), element(2, Arg2))), 187: {ok, Response} = request(Path, "POST", Args, admin), 188: check_status_code(Response, 201), 189: check_location_header(Response, list_to_binary(build_path_prefix()++"/api/weather/10/subcategory/" ++ Result)). 190: 191: put_simple(_Config) -> 192: Binds = [{arg1, <<"username">>}, {arg2,<<"localhost">>}], 193: Args = [{arg3, <<"newusername">>}], 194: Base = "/api/users", 195: {ok, Response} = request(create_path_with_binds(Base, Binds), "PUT", Args, admin), 196: check_status_code(Response, 204). 197: 198: get_two_args(_Config) -> 199: Arg1 = {arg1, 1}, 200: Arg2 = {arg2, 2}, 201: Base = "/api/animals", 202: ExpectedBody = get_two_args_command(element(2, Arg1), element(2, Arg2)), 203: {ok, Response} = request(create_path_with_binds(Base, [Arg1, Arg2]), "GET", admin), 204: check_status_code(Response, 200), 205: check_response_body(Response, ExpectedBody). 206: 207: get_two_args_different_types(_Config) -> 208: Arg1 = {one, 1}, 209: Arg2 = {two, <<"mybin">>}, 210: Base = "/api/books", 211: ExpectedBody = get_two_args2_command(element(2, Arg1), element(2, Arg2)), 212: {ok, Response} = request(create_path_with_binds(Base, [Arg1, Arg2]), "GET", admin), 213: check_status_code(Response, 200), 214: check_response_body(Response, ExpectedBody). 215: 216: get_wrong_path(_Config) -> 217: Path = <<"/api/animals2/1/2">>, 218: {ok, Response} = request(Path, "GET", admin), 219: check_status_code(Response, 404). 220: 221: get_wrong_arg_number(_Config) -> 222: Path = <<"/api/animals/1/2/3">>, 223: {ok, Response} = request(Path, "GET", admin), 224: check_status_code(Response, 404). 225: 226: get_no_command(_Config) -> 227: Path = <<"/api/unregistered_command/123123">>, 228: {ok, Response} = request(Path, "GET", admin), 229: check_status_code(Response, 404). 230: 231: get_wrong_arg_type(_Config) -> 232: Path = <<"/api/animals/1/wrong">>, 233: {ok, Response} = request(Path, "GET", admin), 234: check_status_code(Response, 400). 235: 236: post_wrong_arg_number(_Config) -> 237: Args = [{arg1, 10}, {arg2,2}, {arg3, 100}], 238: Path = <<"/api/weather">>, 239: {ok, Response} = request(Path, "POST", Args, admin), 240: check_status_code(Response, 404). 241: 242: post_wrong_arg_name(_Config) -> 243: Args = [{arg11, 10}, {arg2,2}], 244: Path = <<"/api/weather">>, 245: {ok, Response} = request(Path, "POST", Args, admin), 246: check_status_code(Response, 400). 247: 248: post_wrong_arg_type(_Config) -> 249: Args = [{arg1, 10}, {arg2,<<"weird binary">>}], 250: Path = <<"/api/weather">>, 251: {ok, Response} = request(Path, "POST", Args, admin), 252: check_status_code(Response, 400). 253: 254: post_different_arg_order(_Config) -> 255: Arg1 = {arg1, 10}, 256: Arg2 = {arg2, 2}, 257: Args = [Arg2, Arg1], 258: Path = <<"/api/weather">>, 259: Result = binary_to_list(post_simple_command(element(2, Arg1), element(2, Arg2))), 260: {ok, Response} = request(Path, "POST", Args, admin), 261: check_status_code(Response, 201), 262: check_location_header(Response, list_to_binary(build_path_prefix() ++"/api/weather/" ++ Result)). 263: 264: post_no_command(_Config) -> 265: Args = [{arg1, 10}, {arg2,2}], 266: Path = <<"/api/weather/10">>, 267: {ok, Response} = request(Path, "POST", Args, admin), 268: check_status_code(Response, 404). 269: 270: 271: delete_wrong_arg_order(_Config) -> 272: Arg1 = {arg1, <<"ala_ma_kota">>}, 273: Arg2 = {arg2, 2}, 274: Base = "/api/music", 275: {ok, Response} = request(create_path_with_binds(Base, [Arg2, Arg1]), "DELETE", admin), 276: check_status_code(Response, 400). 277: 278: delete_wrong_arg_types(_Config) -> 279: Arg1 = {arg1, 2}, 280: Arg2 = {arg2, <<"ala_ma_kota">>}, 281: Base = "/api/music", 282: {ok, Response} = request(create_path_with_binds(Base, [Arg1, Arg2]), "DELETE", admin), 283: check_status_code(Response, 400). 284: 285: put_wrong_param_type(_Config) -> 286: Binds = [{username, <<"username">>}, {domain, <<"domain">>}], 287: Parameters = [{age, <<"23">>}, {kids, 10}], 288: Base = "/api/dragons", 289: {ok, Response} = request(create_path_with_binds(Base, Binds), "PUT", Parameters, admin), 290: check_status_code(Response, 400). 291: 292: put_wrong_bind_type(_Config) -> 293: Binds = [{username, <<"username">>}, {domain, 123}], 294: Parameters = [{age, 23}, {kids, 10}], 295: Base = "/api/dragons", 296: {ok, Response} = request(create_path_with_binds(Base, Binds), "PUT", Parameters, admin), 297: check_status_code(Response, 400). 298: 299: put_different_params_order(_Config) -> 300: Binds = [{username, <<"username">>}, {domain, <<"domain">>}], 301: Parameters = [{kids, 2}, {age, 45}], 302: Base = "/api/dragons", 303: {ok, Response} = request(create_path_with_binds(Base, Binds), "PUT", Parameters, admin), 304: check_status_code(Response, 200). 305: 306: put_wrong_binds_order(_Config) -> 307: Binds = [{domain, <<"domain">>}, {username, <<"username">>}], 308: Parameters = [{kids, 2}, {age, 30}], 309: Base = "/api/dragons", 310: {ok, Response} = request(create_path_with_binds(Base, Binds), "PUT", Parameters, admin), 311: check_status_code(Response, 400). 312: 313: put_too_less_params(_Config) -> 314: Binds = [{username, <<"username">>}, {domain, <<"domain">>}], 315: Parameters = [{kids, 3}], 316: Base = "/api/dragons", 317: {ok, Response} = request(create_path_with_binds(Base, Binds), "PUT", Parameters, admin), 318: check_status_code(Response, 400). 319: 320: put_too_less_binds(_Config) -> 321: Binds = [{username, <<"username">>}], 322: Parameters = [{age, 20}, {kids, 3}], 323: Base = "/api/dragons", 324: {ok, Response} = request(create_path_with_binds(Base, Binds), "PUT", Parameters, admin), 325: check_status_code(Response, 404). 326: 327: put_wrong_bind_name(_Config) -> 328: Binds = [{usersrejm, <<"username">>}, {domain, <<"localhost">>}], 329: Parameters = [{age, 20}, {kids, 3}], 330: Base = "/api/dragons", 331: {ok, Response} = request(create_path_with_binds(Base, Binds), "PUT", Parameters, admin), 332: check_status_code(Response, 404). 333: 334: put_wrong_param_name(_Config) -> 335: Binds = [{username, <<"username">>}, {domain, <<"localhost">>}], 336: Parameters = [{age, 20}, {srids, 3}], 337: Base = "/api/dragons", 338: {ok, Response} = request(create_path_with_binds(Base, Binds), "PUT", Parameters, admin), 339: check_status_code(Response, 404). 340: 341: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 342: %%%% Client side tests 343: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 344: 345: get_simple_client(_Config) -> 346: Arg = {arg1, <<"bob@localhost">>}, 347: Base = "/api/clients", 348: Username = <<"username@localhost">>, 349: Auth = {binary_to_list(Username), "secret"}, 350: ExpectedBody = get_simple_client_command(Username, element(2, Arg)), 351: {ok, Response} = request(create_path_with_binds(Base, [Arg]), "GET", {Auth, true}), 352: check_status_code(Response, 200), 353: check_response_body(Response, ExpectedBody). 354: 355: get_two_args_client(_Config) -> 356: Arg1 = {other, <<"bob@localhost">>}, 357: Arg2 = {limit, 10}, 358: Base = "/api/message", 359: Username = <<"alice@localhost">>, 360: Auth = {binary_to_list(Username), "secret"}, 361: ExpectedBody = get_two_args_client_command(Username, element(2, Arg1), element(2, Arg2)), 362: {ok, Response} = request(create_path_with_binds(Base, [Arg1, Arg2]), "GET", {Auth, true}), 363: check_status_code(Response, 200), 364: check_response_body(Response, ExpectedBody). 365: 366: get_bad_auth(_Config) -> 367: Arg = {arg1, <<"bob@localhost">>}, 368: Base = "/api/clients", 369: Username = <<"username@localhost">>, 370: Auth = {binary_to_list(Username), "secret"}, 371: get_simple_client_command(Username, element(2, Arg)), 372: {ok, Response} = request(create_path_with_binds(Base, [Arg]), "GET", {Auth, false}), 373: check_status_code(Response, 401). 374: 375: post_simple_client(_Config) -> 376: Arg1 = {title, <<"Juliet's despair">>}, 377: Arg2 = {content, <<"If they do see thee, they will murder thee!">>}, 378: Base = <<"/api/ohmyromeo">>, 379: Username = <<"username@localhost">>, 380: Auth = {binary_to_list(Username), "secret"}, 381: Result = binary_to_list(post_simple_client_command(Username, element(2, Arg1), element(2, Arg2))), 382: {ok, Response} = request(Base, "POST", [Arg1, Arg2], {Auth, true}), 383: check_status_code(Response, 201), 384: check_location_header(Response, list_to_binary(build_path_prefix() ++"/api/ohmyromeo/" ++ Result)). 385: 386: put_simple_client(_Config) -> 387: Arg = {password, <<"ilovepancakes">>}, 388: Base = <<"/api/superusers">>, 389: Username = <<"joe@localhost">>, 390: Auth = {binary_to_list(Username), "secretpassword"}, 391: put_simple_client_command(Username, element(2, Arg)), 392: {ok, Response} = request(Base, "PUT", [Arg], {Auth, true}), 393: check_status_code(Response, 204). 394: 395: delete_simple_client(_Config) -> 396: Arg = {name, <<"giant">>}, 397: Base = "/api/bikes", 398: Username = <<"username@localhost">>, 399: Auth = {binary_to_list(Username), "secret"}, 400: get_simple_client_command(Username, element(2, Arg)), 401: {ok, Response} = request(create_path_with_binds(Base, [Arg]), "DELETE", {Auth, true}), 402: check_status_code(Response, 204). 403: 404: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 405: %%%% definitions 406: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 407: 408: commands_client() -> 409: [ 410: [ 411: {name, get_simple_client}, 412: {category, <<"clients">>}, 413: {desc, <<"do nothing and return">>}, 414: {module, ?MODULE}, 415: {function, get_simple_client_command}, 416: {action, read}, 417: {identifiers, []}, 418: {security_policy, [user]}, 419: {args, [{caller, binary}, {arg1, binary}]}, 420: {result, {result, binary}} 421: ], 422: [ 423: {name, get_two_args_client}, 424: {category, <<"message">>}, 425: {desc, <<"do nothing and return">>}, 426: {module, ?MODULE}, 427: {function, get_two_args_client_command}, 428: {action, read}, 429: {identifiers, []}, 430: {security_policy, [user]}, 431: {args, [{caller, binary}, {other, binary}, {limit, integer}]}, 432: {result, {result, binary}} 433: ], 434: [ 435: {name, post_simple_client}, 436: {category, <<"ohmyromeo">>}, 437: {desc, <<"do nothing and return">>}, 438: {module, ?MODULE}, 439: {function, post_simple_client_command}, 440: {action, create}, 441: {identifiers, []}, 442: {security_policy, [user]}, 443: {args, [{caller, binary}, {title, binary}, {content, binary}]}, 444: {result, {result, binary}} 445: ], 446: [ 447: {name, put_simple_client}, 448: {category, <<"superusers">>}, 449: {desc, <<"do nothing and return">>}, 450: {module, ?MODULE}, 451: {function, put_simple_client_command}, 452: {action, update}, 453: {identifiers, [caller]}, 454: {security_policy, [user]}, 455: {args, [{caller, binary}, {password, binary}]}, 456: {result, ok} 457: ], 458: [ 459: {name, delete_simple_client}, 460: {category, <<"bikes">>}, 461: {desc, <<"do nothing and return">>}, 462: {module, ?MODULE}, 463: {function, delete_simple_client_command}, 464: {action, delete}, 465: {identifiers, []}, 466: {security_policy, [user]}, 467: {args, [{caller, binary}, {name, binary}]}, 468: {result, ok} 469: ] 470: ]. 471: 472: commands_admin() -> 473: [ 474: [ 475: {name, get_simple}, 476: {category, <<"users">>}, 477: {desc, <<"do nothing and return">>}, 478: {module, ?MODULE}, 479: {function, get_simple_command}, 480: {action, read}, 481: {identifiers, []}, 482: {args, [{arg1, binary}]}, 483: {result, {result, binary}} 484: ], 485: [ 486: {name, get_advanced}, 487: {category, <<"animals">>}, 488: {desc, <<"do nothing and return">>}, 489: {module, ?MODULE}, 490: {function, get_two_args_command}, 491: {action, read}, 492: {identifiers, []}, 493: {args, [{arg1, integer}, {arg2, integer}]}, 494: {result, {result, binary}} 495: ], 496: [ 497: {name, get_advanced2}, 498: {category, <<"books">>}, 499: {desc, <<"do nothing and return">>}, 500: {module, ?MODULE}, 501: {function, get_two_args2_command}, 502: {action, read}, 503: {identifiers, []}, 504: {args, [{one, integer}, {two, binary}]}, 505: {result, {result, integer}} 506: ], 507: [ 508: {name, post_simple}, 509: {category, <<"weather">>}, 510: {desc, <<"do nothing and return">>}, 511: {module, ?MODULE}, 512: {function, post_simple_command}, 513: {action, create}, 514: {identifiers, []}, 515: {args, [{arg1, integer}, {arg2, integer}]}, 516: {result, {result, binary}} 517: ], 518: [ 519: {name, post_simple2}, 520: {category, <<"weather">>}, 521: {subcategory, <<"subcategory">>}, 522: {desc, <<"do nothing and return">>}, 523: {module, ?MODULE}, 524: {function, post_simple_command}, 525: {action, create}, 526: {identifiers, [arg1]}, 527: {args, [{arg1, integer}, {arg2, integer}]}, 528: {result, {result, binary}} 529: ], 530: [ 531: {name, delete_simple}, 532: {category, <<"music">>}, 533: {desc, <<"do nothing and return">>}, 534: {module, ?MODULE}, 535: {function, delete_simple_command}, 536: {action, delete}, 537: {identifiers, []}, 538: {args, [{arg1, binary}, {arg2, integer}]}, 539: {result, ok} 540: ], 541: [ 542: {name, put_simple}, 543: {category, <<"users">>}, 544: {desc, <<"do nothing and return">>}, 545: {module, ?MODULE}, 546: {function, put_simple_command}, 547: {action, update}, 548: {args, [{arg1, binary}, {arg2, binary}, {arg3, binary}]}, 549: {identifiers, [arg1, arg2]}, 550: {result, ok} 551: ], 552: [ 553: {name, put_advanced}, 554: {category, <<"dragons">>}, 555: {desc, <<"do nothing and return">>}, 556: {module, ?MODULE}, 557: {function, put_advanced_command}, 558: {action, update}, 559: {args, [{username, binary}, 560: {domain, binary}, 561: {age, integer}, 562: {kids, integer}]}, 563: {identifiers, [username, domain]}, 564: {result, ok} 565: ] 566: ]. 567: 568: commands_new() -> 569: commands_admin() ++ commands_client(). 570: 571: 572: %% admin command funs 573: get_simple_command(<<"bob@localhost">>) -> 574: <<"bob is OK">>. 575: 576: get_two_args_command(1, 2) -> 577: <<"all is working">>. 578: 579: get_two_args2_command(X, B) when is_integer(X) and is_binary(B) -> 580: 100. 581: 582: post_simple_command(_X, 2) -> 583: <<"new_resource">>. 584: 585: delete_simple_command(Binary, 2) when is_binary(Binary) -> 586: 10. 587: 588: put_simple_command(_Arg1, _Arg2, _Arg3) -> 589: ok. 590: 591: put_advanced_command(Arg1, Arg2, Arg3, Arg4) when is_binary(Arg1) and is_binary(Arg2) 592: and is_integer(Arg3) and is_integer(Arg4) -> 593: ok. 594: 595: %% clients command funs 596: get_simple_client_command(_Caller, _SomeBinary) -> 597: <<"client bob is OK">>. 598: 599: get_two_args_client_command(_Caller, _SomeBinary, _SomeInteger) -> 600: <<"client2 bob is OK">>. 601: 602: post_simple_client_command(_Caller, _Title, _Content) -> 603: <<"new_resource">>. 604: 605: put_simple_client_command(_Username, _Password) -> 606: changed. 607: 608: delete_simple_client_command(_Username, _BikeName) -> 609: changed. 610: 611: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 612: %%%% utilities 613: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 614: build_path_prefix() -> 615: "http://" ++ ?HOST ++ ":" ++ integer_to_list(?PORT). 616: 617: maybe_add_body([]) -> 618: []; 619: maybe_add_body(Args) -> 620: jiffy:encode(maps:from_list(Args)). 621: 622: maybe_add_accepted_headers("POST") -> 623: accepted_headers(); 624: maybe_add_accepted_headers("PUT") -> 625: accepted_headers(); 626: maybe_add_accepted_headers(_) -> 627: []. 628: 629: accepted_headers() -> 630: [{<<"Content-Type">>, <<"application/json">>}, {<<"Accept">>, <<"application/json">>}]. 631: 632: maybe_add_auth_header({User, Password}) -> 633: Basic = list_to_binary("Basic " ++ base64:encode_to_string(User ++ ":"++ Password)), 634: [{<<"authorization">>, Basic}]; 635: maybe_add_auth_header(admin) -> 636: []. 637: 638: -spec create_path_with_binds(string(), list()) -> binary(). 639: create_path_with_binds(Base, ArgList) when is_list(ArgList) -> 640: list_to_binary( 641: lists:flatten(Base ++ ["/" ++ to_list(ArgValue) 642: || {ArgName, ArgValue} <- ArgList])). 643: 644: to_list(Int) when is_integer(Int) -> 645: integer_to_list(Int); 646: to_list(Float) when is_float(Float) -> 647: float_to_list(Float); 648: to_list(Bin) when is_binary(Bin) -> 649: binary_to_list(Bin); 650: to_list(Atom) when is_atom(Atom) -> 651: atom_to_list(Atom); 652: to_list(Other) -> 653: Other. 654: 655: -spec request(binary(), method(), admin | {{binary(), binary()}, boolean()}) -> any. 656: request(Path, "GET", Entity) -> 657: request(Path, "GET", [], Entity); 658: request(Path, "DELETE", Entity) -> 659: request(Path, "DELETE", [], Entity). 660: 661: -spec request(binary(), method(), list({atom(), any()}), 662: {headers, list()} | admin | {{binary(), binary()}, boolean()}) -> any. 663: do_request(Path, Method, Body, {headers, Headers}) -> 664: {ok, Pid} = fusco:start_link("http://"++ ?HOST ++ ":" ++ integer_to_list(?PORT), []), 665: R = fusco:request(Pid, Path, Method, Headers, Body, 5000), 666: fusco:disconnect(Pid), 667: teardown(), 668: R. 669: 670: request(Path, Method, BodyData, {{_User, _Pass} = Auth, Authorized}) -> 671: setup(client_module()), 672: meck:expect(ejabberd_auth, check_password, fun(_, _) -> Authorized end), 673: Body = maybe_add_body(BodyData), 674: AuthHeader = maybe_add_auth_header(Auth), 675: AcceptHeader = maybe_add_accepted_headers(Method), 676: do_request(Path, Method, Body, {headers, AuthHeader ++ AcceptHeader}); 677: request(Path, Method, BodyData, admin) -> 678: ct:pal("~p, ~p, ~p", [Path, Method, BodyData]), 679: setup(backend_module()), 680: Body = maybe_add_body(BodyData), 681: AcceptHeader = maybe_add_accepted_headers(Method), 682: do_request(Path, Method, Body, {headers, AcceptHeader}). 683: 684: mc_holder() -> 685: erlang:register(mc_holder_proc, self()), 686: mongoose_commands:init(), 687: mongoose_commands:register(commands_new()), 688: receive 689: _ -> ok 690: end, 691: erlang:unregister(mc_holder_proc). 692: 693: check_status_code(Response, Code) when is_integer(Code) -> 694: {{ResCode, _}, _, _, _, _} = Response, 695: ?assertEqual(Code, binary_to_integer(ResCode)); 696: check_status_code(_R, Code) -> 697: ?assertEqual(Code, not_a_number). 698: 699: check_response_body(Response, ExpectedBody) -> 700: {_, _, Body, _ , _} = Response, 701: ?assertEqual(binary_to_list(Body), "\"" ++ binary_to_list(ExpectedBody) ++ "\""). 702: 703: check_location_header(Response, Path) -> 704: {_, Headers, _, _ , _} = Response, 705: Location = proplists:get_value(<<"location">>, Headers), 706: ?assertEqual(Path, Location).