1: %% -*- coding: utf-8 -*- 2: %% 3: %% %CopyrightBegin% 4: %% 5: %% Copyright Ericsson AB 2000-2012. All Rights Reserved. 6: %% 7: %% The contents of this file are subject to the Erlang Public License, 8: %% Version 1.1, (the "License"); you may not use this file except in 9: %% compliance with the License. You should have received a copy of the 10: %% Erlang Public License along with this software. If not, it can be 11: %% retrieved online at http://www.erlang.org/. 12: %% 13: %% Software distributed under the License is distributed on an "AS IS" 14: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 15: %% the License for the specific language governing rights and limitations 16: %% under the License. 17: %% 18: %% %CopyrightEnd% 19: 20: -module(xref_SUITE). 21: 22: %-define(debug, true). 23: 24: -ifdef(debug). 25: -define(format(S, A), io:format(S, A)). 26: -define(line, put(line, ?LINE), ). 27: -define(config(X,Y), "./log_dir/"). 28: -define(t,test_server). 29: -define(datadir, "xref_SUITE_data"). 30: -define(privdir, "xref_SUITE_priv"). 31: -define(copydir, "xref_SUITE_priv/datacopy"). 32: -else. 33: -include_lib("test_server/include/test_server.hrl"). 34: -define(format(S, A), ok). 35: -define(datadir, ?config(data_dir, Conf)). 36: -define(privdir, ?config(priv_dir, Conf)). 37: -define(copydir, ?config(copy_dir, Conf)). 38: -endif. 39: 40: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 41: init_per_group/2,end_per_group/2, init/1, fini/1]). 42: 43: -export([ 44: addrem/1, convert/1, intergraph/1, lines/1, loops/1, 45: no_data/1, modules/1]). 46: 47: -export([ 48: add/1, default/1, info/1, lib/1, read/1, read2/1, remove/1, 49: replace/1, update/1, deprecated/1, trycatch/1, 50: fun_mfa/1, fun_mfa_r14/1, 51: fun_mfa_vars/1, qlc/1]). 52: 53: -export([ 54: analyze/1, basic/1, md/1, q/1, variables/1, unused_locals/1]). 55: 56: -export([ 57: format_error/1, otp_7423/1, otp_7831/1, otp_10192/1]). 58: 59: -import(lists, [append/2, flatten/1, keysearch/3, member/2, sort/1, usort/1]). 60: 61: -import(sofs, [converse/1, from_term/1, intersection/2, is_sofs_set/1, 62: range/1, relation_to_family/1, set/1, to_external/1, 63: union/2]). 64: 65: -export([init_per_testcase/2, end_per_testcase/2]). 66: 67: %% Checks some info counters of a server and some relations that should hold. 68: -export([check_count/1, check_state/1]). 69: 70: -include_lib("kernel/include/file.hrl"). 71: 72: -include_lib("tools/src/xref.hrl"). 73: 74: suite() -> [{ct_hooks,[ts_install_cth]}]. 75: 76: all() -> 77: [{group, xref}, {group, files}, {group, analyses}, 78: {group, misc}]. 79: 80: groups() -> 81: [{xref, [], 82: [addrem, convert, intergraph, lines, loops, no_data, 83: modules]}, 84: {files, [], 85: [add, default, info, lib, read, read2, remove, replace, 86: update, deprecated, trycatch, fun_mfa, 87: fun_mfa_r14, fun_mfa_vars, qlc]}, 88: {analyses, [], 89: [analyze, basic, md, q, variables, unused_locals]}, 90: {misc, [], [format_error, otp_7423, otp_7831, otp_10192]}]. 91: 92: init_per_suite(Config) -> 93: init(Config). 94: 95: end_per_suite(_Config) -> 96: ok. 97: 98: init_per_group(_GroupName, Config) -> 99: Config. 100: 101: end_per_group(_GroupName, Config) -> 102: Config. 103: 104: 105: init(Conf) when is_list(Conf) -> 106: DataDir = ?datadir, 107: PrivDir = ?privdir, 108: ?line CopyDir = fname(PrivDir, "datacopy"), 109: ?line TarFile = fname(PrivDir, "datacopy.tgz"), 110: ?line {ok, Tar} = erl_tar:open(TarFile, [write, compressed]), 111: ?line ok = erl_tar:add(Tar, DataDir, CopyDir, [compressed]), 112: ?line ok = erl_tar:close(Tar), 113: ?line ok = erl_tar:extract(TarFile, [compressed]), 114: ?line ok = file:delete(TarFile), 115: [{copy_dir, CopyDir} | Conf]. 116: 117: fini(Conf) when is_list(Conf) -> 118: %% Nothing. 119: Conf. 120: 121: init_per_testcase(_Case, Config) -> 122: Dog=?t:timetrap(?t:minutes(2)), 123: [{watchdog, Dog}|Config]. 124: 125: end_per_testcase(_Case, _Config) -> 126: Dog=?config(watchdog, _Config), 127: test_server:timetrap_cancel(Dog), 128: ok. 129: 130: 131: %% Seems a bit short... 132: addrem(suite) -> []; 133: addrem(doc) -> ["Simple test of removing modules"]; 134: addrem(Conf) when is_list(Conf) -> 135: S0 = new(), 136: 137: F1 = {m1,f1,1}, 138: F2 = {m2,f1,2}, 139: 140: E1 = {F1,F2}, 141: E2 = {F2,F1}, 142: 143: D1 = {F1,12}, 144: DefAt_m1 = [D1], 145: X_m1 = [F1], 146: % L_m1 = [], 147: XC_m1 = [E1], 148: LC_m1 = [], 149: LCallAt_m1 = [], 150: XCallAt_m1 = [{E1,13}], 151: Info1 = #xref_mod{name = m1, app_name = [a1]}, 152: ?line S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, 153: XC_m1, LC_m1), 154: 155: D2 = {F2,7}, 156: DefAt_m2 = [D2], 157: X_m2 = [F2], 158: % L_m2 = [], 159: XC_m2 = [E2], 160: LC_m2 = [], 161: LCallAt_m2 = [], 162: XCallAt_m2 = [{E2,96}], 163: Info2 = #xref_mod{name = m2, app_name = [a2]}, 164: ?line S2 = add_module(S1, Info2, DefAt_m2, X_m2, LCallAt_m2, XCallAt_m2, 165: XC_m2, LC_m2), 166: 167: ?line S5 = set_up(S2), 168: 169: ?line {ok, XMod1, S6} = remove_module(S5, m1), 170: ?line [a1] = XMod1#xref_mod.app_name, 171: ?line {ok, XMod2, S6a} = remove_module(S6, m2), 172: ?line [a2] = XMod2#xref_mod.app_name, 173: ?line S7 = set_up(S6a), 174: 175: ?line AppInfo1 = #xref_app{name = a1, rel_name = [r1]}, 176: ?line S9 = add_application(S7, AppInfo1), 177: ?line S10 = set_up(S9), 178: ?line AppInfo2 = #xref_app{name = a2, rel_name = [r1]}, 179: ?line _S11 = add_application(S10, AppInfo2), 180: ok. 181: 182: convert(suite) -> []; 183: convert(doc) -> ["Coercion of data"]; 184: convert(Conf) when is_list(Conf) -> 185: S0 = new(), 186: 187: F1 = {m1,f1,1}, 188: F6 = {m1,f2,6}, % X 189: F2 = {m2,f1,2}, 190: F3 = {m2,f2,3}, % X 191: F7 = {m2,f3,7}, % X 192: F4 = {m3,f1,4}, % X 193: F5 = {m3,f2,5}, 194: 195: UF1 = {m1,f12,17}, 196: UF2 = {m17,f17,177}, 197: 198: E1 = {F1,F3}, % X 199: E2 = {F6,F7}, % X 200: E3 = {F2,F6}, % X 201: E4 = {F1,F4}, % X 202: E5 = {F4,F5}, 203: E6 = {F7,F4}, % X 204: 205: UE1 = {F2,UF2}, % X 206: UE2 = {F5,UF1}, % X 207: 208: D1 = {F1,12}, 209: D6 = {F6,3}, 210: DefAt_m1 = [D1,D6], 211: X_m1 = [F6], 212: % L_m1 = [F1], 213: XC_m1 = [E1,E2,E4], 214: LC_m1 = [], 215: LCallAt_m1 = [], 216: XCallAt_m1 = [{E1,13},{E2,17},{E4,7}], 217: Info1 = #xref_mod{name = m1, app_name = [a1]}, 218: ?line S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, 219: XC_m1, LC_m1), 220: 221: D2 = {F2,7}, 222: D3 = {F3,9}, 223: D7 = {F7,19}, 224: DefAt_m2 = [D2,D3,D7], 225: X_m2 = [F3,F7], 226: % L_m2 = [F2], 227: XC_m2 = [E3,E6,UE1], 228: LC_m2 = [], 229: LCallAt_m2 = [], 230: XCallAt_m2 = [{E3,96},{E6,12},{UE1,77}], 231: Info2 = #xref_mod{name = m2, app_name = [a2]}, 232: ?line S2 = add_module(S1, Info2, DefAt_m2, X_m2, LCallAt_m2, XCallAt_m2, 233: XC_m2, LC_m2), 234: 235: D4 = {F4,6}, 236: D5 = {F5,97}, 237: DefAt_m3 = [D4,D5], 238: X_m3 = [F4], 239: % L_m3 = [F5], 240: XC_m3 = [UE2], 241: LC_m3 = [E5], 242: LCallAt_m3 = [{E5,19}], 243: XCallAt_m3 = [{UE2,22}], 244: Info3 = #xref_mod{name = m3, app_name = [a3]}, 245: ?line S3 = add_module(S2, Info3, DefAt_m3, X_m3, LCallAt_m3, XCallAt_m3, 246: XC_m3, LC_m3), 247: 248: Info4 = #xref_mod{name = m4, app_name = [a2]}, 249: ?line S4 = add_module(S3, Info4, [], [], [], [], [], []), 250: 251: AppInfo1 = #xref_app{name = a1, rel_name = [r1]}, 252: ?line S9 = add_application(S4, AppInfo1), 253: AppInfo2 = #xref_app{name = a2, rel_name = [r1]}, 254: ?line S10 = add_application(S9, AppInfo2), 255: AppInfo3 = #xref_app{name = a3, rel_name = [r2]}, 256: ?line S11 = add_application(S10, AppInfo3), 257: 258: RelInfo1 = #xref_rel{name = r1}, 259: ?line S12 = add_release(S11, RelInfo1), 260: RelInfo2 = #xref_rel{name = r2}, 261: ?line S13 = add_release(S12, RelInfo2), 262: 263: ?line S = set_up(S13), 264: 265: ?line {ok, _} = eval("(Lin)(m1->m1:Mod) * m1->m1", type_error, S), 266: ?line {ok, _} = eval("(XXL)(Lin)(m1->m1:Mod) * m1->m1", type_error, S), 267: 268: ?line AllDefAt = eval("(Lin) M", S), 269: ?line AllV = eval("(Fun) M", S), 270: ?line AllCallAt = eval("(XXL)(Lin) E", S), 271: ?line AllE = eval("E", S), 272: 273: ?line AM = eval("AM", S), 274: ?line A = eval("A", S), 275: ?line R = eval("R", S), 276: 277: 278: % vertices 279: % general 1 step 280: ?line {ok, _} = eval("(Fun) (Lin) M", AllV, S), 281: ?line {ok, _} = eval("(Fun) (Lin) (Lin) M", AllV, S), 282: ?line {ok, _} = eval(f("(Fun) (Lin) ~p", [[F1, F3]]), [F1,F3], S), 283: ?line {ok, _} = eval(f("(Mod) ~p", [AllV]), [m1,m17,m2,m3], S), 284: ?line {ok, _} = eval(f("(Mod) ~p", [[F1,F3,F6]]), [m1,m2], S), 285: ?line {ok, _} = eval("(App) M", A, S), 286: ?line {ok, _} = eval(f("(App) ~p", [[m1,m2,m4]]), [a1,a2], S), 287: ?line {ok, _} = eval(f("(Rel) ~p", [A]), R, S), 288: ?line {ok, _} = eval(f("(Rel) ~p", [[a1,a2,a2]]), [r1], S), 289: % general 2 steps 290: ?line {ok, _} = eval("(Mod) (Lin) M", [m1,m17,m2,m3], S), 291: ?line {ok, _} = eval(f("(App) ~p", [AllV]), [a1,a2,a3], S), 292: ?line {ok, _} = eval("(Rel) M", R, S), 293: % general 4 steps 294: ?line {ok, _} = eval("(Rel) (Lin) M", [r1,r2], S), 295: 296: % special 1 step 297: ?line {ok, _} = eval(f("(Lin) ~p", [AllV]), AllDefAt, S), 298: ?line {ok, _} = eval(f("(Lin) ~p", [[F1,F3]]), [{F1,12},{F3,9}], S), 299: ?line {ok, _} = eval("(Fun) M", AllV, S), 300: ?line {ok, _} = eval(f("(Fun) ~p", [[m1,m2]]), [F1,F2,F3,F6,F7,UF1], S), 301: ?line {ok, _} = eval(f("(Mod) ~p", [A]), AM, S), 302: ?line {ok, _} = eval(f("(Mod) ~p", [[a1,a2]]), [m1,m2,m4], S), 303: ?line {ok, _} = eval(f("(App) ~p", [R]), A, S), 304: ?line {ok, _} = eval(f("(App) ~p", [[r1]]), [a1,a2], S), 305: % special 2 steps 306: ?line {ok, _} = eval("(Lin) M", AllDefAt, S), 307: ?line AnalyzedV = eval("(Fun) AM", S), 308: ?line {ok, _} = eval(f("(Fun) ~p", [A]), AnalyzedV, S), 309: ?line {ok, _} = eval(f("(Mod) ~p", [R]), AM, S), 310: % special 4 steps 311: ?line AnalyzedAllDefAt = eval("(Lin) AM", S), 312: ?line {ok, _} = eval("(Lin) R", AnalyzedAllDefAt, S), 313: 314: % edges 315: Ms = [{m1,m2},{m1,m3},{m2,m1},{m2,m3},{m3,m3}], 316: UMs = [{m2,m17},{m3,m1}], 317: AllMs = append(Ms, UMs), 318: As = [{a1,a2},{a1,a3},{a2,a1},{a2,a3},{a3,a3}], 319: Rs = [{r1,r1},{r1,r2},{r2,r2}], 320: 321: % general 1 step 322: ?line {ok, _} = eval("(Fun) (Lin) E", AllE, S), 323: ?line {ok, _} = eval(f("(Fun)(Lin) ~p", [[E1, E6]]), [E1, E6], S), 324: ?line {ok, _} = eval("(Mod) E", AllMs, S), 325: ?line {ok, _} = eval(f("(Mod) ~p", [[E1, E6]]), [{m1,m2},{m2,m3}], S), 326: ?line {ok, _} = eval(f("(App) ~p", [As]), As, S), 327: ?line {ok, _} = eval("(App) [m1->m2,m2->m3]", [{a1,a2},{a2,a3}], S), 328: ?line {ok, _} = eval(f("(Rel) ~p", [As]), Rs, S), 329: ?line {ok, _} = eval("(Rel) a1->a2", [{r1,r1}], S), 330: 331: % special 1 step 332: ?line {ok, _} = eval("(XXL) (Lin) (Fun) E", AllCallAt, S), 333: ?line {ok, _} = eval("(XXL) (XXL) (Lin) (Fun) E", AllCallAt, S), 334: 335: ?line {ok, _} = eval(f("(XXL) (Lin) ~p", [[E1, E6]]), 336: [{{D1,D3},[13]}, {{D7,D4},[12]}], S), 337: ?line {ok, _} = eval(f("(Fun) ~p", [AllMs]), AllE, S), 338: ?line {ok, _} = eval("(Fun) [m1->m2,m2->m3]", [E1,E2,E6], S), 339: ?line {ok, _} = eval(f("(Mod) ~p", [As]), Ms, S), 340: ?line {ok, _} = eval("(Mod) [a1->a2,a2->a3]", [{m1,m2},{m2,m3}], S), 341: ?line {ok, _} = eval(f("(App) ~p", [Rs]), As, S), 342: ?line {ok, _} = eval("(App) r1->r1", [{a1,a2},{a2,a1}], S), 343: ok. 344: 345: intergraph(suite) -> []; 346: intergraph(doc) -> ["Inter Call Graph"]; 347: intergraph(Conf) when is_list(Conf) -> 348: S0 = new(), 349: 350: F1 = {m1,f1,1}, % X 351: F2 = {m1,f2,2}, % X 352: F3 = {m1,f3,3}, 353: F4 = {m1,f4,4}, 354: F5 = {m1,f5,5}, 355: 356: F6 = {m2,f1,6}, % X 357: F7 = {m2,f1,7}, 358: F8 = {m2,f1,8}, 359: F9 = {m2,f1,9}, 360: F10 = {m2,f1,10}, 361: F11 = {m2,f1,11}, 362: 363: % Note: E1 =:= E4! 364: E1 = {F2,F1}, 365: E2 = {F2,F3}, 366: E3 = {F3,F1}, 367: E4 = {F2,F1}, % X 368: E5 = {F4,F2}, 369: E6 = {F5,F4}, 370: E7 = {F4,F5}, 371: 372: E8 = {F6,F7}, 373: E9 = {F7,F8}, 374: E10 = {F8,F1}, % X 375: E11 = {F6,F9}, 376: E12 = {F6,F10}, 377: E13 = {F9,F11}, 378: E14 = {F10,F11}, 379: E15 = {F11,F1}, % X 380: 381: D1 = {F1,1}, 382: D2 = {F2,2}, 383: D3 = {F3,3}, 384: D4 = {F4,4}, 385: D5 = {F5,5}, 386: DefAt_m1 = [D1,D2,D3,D4,D5], 387: X_m1 = [F1,F2], 388: % L_m1 = [F3,F4,F5], 389: XC_m1 = [E4], 390: LC_m1 = [E1,E2,E3,E5,E6,E7], 391: % Note: E1 and E4 together! 392: LCallAt_m1 = [{E1,1},{E2,2},{E3,3},{E5,5},{E6,6},{E7,7}], 393: XCallAt_m1 = [{E1,4}], 394: Info1 = #xref_mod{name = m1, app_name = [a1]}, 395: ?line S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, 396: XC_m1, LC_m1), 397: 398: D6 = {F6,6}, 399: D7 = {F7,7}, 400: D8 = {F8,8}, 401: D9 = {F9,9}, 402: D10 = {F10,10}, 403: D11 = {F11,11}, 404: DefAt_m2 = [D6,D7,D8,D9,D10,D11], 405: X_m2 = [F6], 406: % L_m2 = [F7,F8,F9,F10,F11], 407: XC_m2 = [E10,E15], 408: LC_m2 = [E8,E9,E11,E12,E13,E14], 409: LCallAt_m2 = [{E8,8},{E9,9},{E11,11},{E12,12},{E13,13},{E14,14}], 410: XCallAt_m2 = [{E10,10},{E15,15}], 411: Info2 = #xref_mod{name = m2, app_name = [a2]}, 412: ?line S2 = add_module(S1, Info2, DefAt_m2, X_m2, LCallAt_m2, XCallAt_m2, 413: XC_m2, LC_m2), 414: 415: AppInfo1 = #xref_app{name = a1, rel_name = [r1]}, 416: ?line S5 = add_application(S2, AppInfo1), 417: AppInfo2 = #xref_app{name = a2, rel_name = [r1]}, 418: ?line S6 = add_application(S5, AppInfo2), 419: 420: RelInfo = #xref_rel{name = r1}, 421: ?line S7 = add_release(S6, RelInfo), 422: 423: ?line S = set_up(S7), 424: 425: ?line {ok, _} = eval("EE | m1", [E1,E5,E6,E7], S), 426: ?line {ok, _} = eval("EE | m2", [{F6,F1}], S), 427: ?line {ok, _} = eval("EE | m2 + EE | m2", [{F6,F1}], S), 428: 429: ?line {ok, _} = eval("(Fun)(Lin)(E | m1)", 430: to_external(union(set(XC_m1), set(LC_m1))), S), 431: ?line {ok, _} = eval("(XXL)(ELin) (EE | m1)", 432: [{{D2,D1},[1,2,4]},{{D4,D2},[5]},{{D5,D4},[6]},{{D4,D5},[7]}], 433: S), 434: ?line {ok, _} = eval("(XXL)(ELin)(EE | m2)", [{{D6,D1},[8,11,12]}], S), 435: ?line {ok, _} = eval("(XXL)(ELin)(ELin)(EE | m2)", 436: [{{D6,D1},[8,11,12]}], S), 437: 438: %% Combining graphs (equal or different): 439: ?line {ok, _} = eval("(XXL)(ELin)(EE | m2 + EE | m2)", 440: [{{D6,D1},[8,11,12]}], S), 441: ?line {ok, _} = eval("(XXL)(ELin)(EE | m2 * EE | m2)", 442: [{{D6,D1},[8,11,12]}], S), 443: ?line {ok, _} = eval("(XXL)(ELin)(EE | m2 - EE | m1)", 444: [{{D6,D1},[8,11,12]}], S), 445: ?line {ok, _} = eval("(XXL)(ELin)(EE | m2 - E | m2)", 446: [{{D6,D1},[8,11,12]}], S), 447: ?line {ok, _} = eval("(XXL)(ELin)(Fun)(ELin)(EE | m2)", 448: [{{D6,D1},[8,11,12]}], S), 449: ?line {ok, _} = eval("EE | m1 + E | m1", LC_m1, S), 450: ?line {ok, _} = eval(f("EE | ~p + E | ~p", [F2, F2]), [E1,E2], S), 451: %% [1,4] from 'calls' is a subset of [1,2,4] from Inter Call Graph: 452: ?line {ok, _} = eval(f("(XXL)(Lin) (E | ~p)", [F2]), 453: [{{D2,D1},[1,4]},{{D2,D3},[2]}], S), 454: 455: ?line {ok, _} = eval(f("(XXL)(ELin) (EE | ~p)", [F2]), 456: [{{D2,D1},[1,2,4]}], S), 457: ?line {ok, _} = eval(f("(XXL)((ELin)(EE | ~p) + (Lin)(E | ~p))", [F2, F2]), 458: [{{D2,D1},[1,2,4]},{{D2,D3},[2]}], S), 459: ?line {ok, _} = 460: eval(f("(XXL)((ELin) ~p + (Lin) ~p)", [{F2, F1}, {F2, F1}]), 461: [{{D2,D1},[1,2,4]}], S), 462: ?line {ok, _} = eval(f("(Fun)(Lin) ~p", [{F2, F1}]), [E1], S), 463: %% The external call E4 is included in the reply: 464: ?line {ok, _} = eval("(XXL)(Lin)(LC | m1)", 465: [{{D2,D1},[1,4]},{{D2,D3},[2]},{{D3,D1},[3]}, 466: {{D4,D2},[5]},{{D4,D5},[7]},{{D5,D4},[6]}], S), 467: %% The local call E1 is included in the reply: 468: ?line {ok, _} = eval("(XXL)(Lin)(XC | m1)", [{{D2,D1},[1,4]}], S), 469: 470: ?line {ok, _} = eval(f("(LLin) (E | ~p || ~p) + (XLin) (E | ~p || ~p)", 471: [F2, F1, F2, F1]), [{E4,[1,4]}], S), 472: 473: ?line {ok, _} = eval("# (ELin) E", 6, S), 474: 475: ok. 476: 477: lines(suite) -> []; 478: lines(doc) -> ["More test of Inter Call Graph, and regular expressions"]; 479: lines(Conf) when is_list(Conf) -> 480: S0 = new(), 481: 482: F1 = {m1,f1,1}, % X 483: F2 = {m1,f2,2}, 484: F3 = {m1,f3,3}, 485: F4 = {m2,f4,4}, % X 486: F5 = {m1,f5,5}, % X 487: F6 = {m1,f6,6}, 488: 489: E1 = {F1,F2}, 490: E2 = {F2,F1}, % X 491: E3 = {F3,F2}, 492: E4 = {F1,F4}, % X 493: E5 = {F2,F4}, % X 494: E6 = {F5,F6}, 495: E7 = {F6,F4}, % X 496: 497: D1 = {F1,1}, 498: D2 = {F2,2}, 499: D3 = {F3,3}, 500: D4 = {F4,4}, 501: D5 = {F5,5}, 502: D6 = {F6,6}, 503: 504: DefAt_m1 = [D1,D2,D3,D5,D6], 505: X_m1 = [F1,F5], 506: % L_m1 = [F2,F3,F6], 507: XC_m1 = [E4,E5,E7], 508: LC_m1 = [E1,E2,E3,E6], 509: LCallAt_m1 = [{E1,1},{E3,3},{E6,6}], 510: XCallAt_m1 = [{E2,2},{E4,4},{E5,5},{E7,7}], 511: Info1 = #xref_mod{name = m1, app_name = [a1]}, 512: ?line S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, 513: XC_m1, LC_m1), 514: 515: DefAt_m2 = [D4], 516: X_m2 = [F4], 517: % L_m2 = [], 518: XC_m2 = [], 519: LC_m2 = [], 520: LCallAt_m2 = [], 521: XCallAt_m2 = [], 522: Info2 = #xref_mod{name = m2, app_name = [a2]}, 523: ?line S2 = add_module(S1, Info2, DefAt_m2, X_m2, LCallAt_m2, XCallAt_m2, 524: XC_m2, LC_m2), 525: 526: AppInfo1 = #xref_app{name = a1, rel_name = [r1]}, 527: ?line S5 = add_application(S2, AppInfo1), 528: AppInfo2 = #xref_app{name = a2, rel_name = [r1]}, 529: ?line S6 = add_application(S5, AppInfo2), 530: 531: RelInfo = #xref_rel{name = r1}, 532: ?line S7 = add_release(S6, RelInfo), 533: 534: ?line S = set_up(S7), 535: 536: ?line {ok, _} = eval("(XXL) (ELin) (EE | m1)", 537: [{{D1,D1},[1]},{{D1,D4},[1,4]},{{D3,D1},[3]},{{D3,D4},[3]}, 538: {{D5,D4},[6]}], S), 539: ?line {ok, _} = eval("(XXL)(Lin) (E | m1)", 540: [{{D1,D2},[1]},{{D1,D4},[4]},{{D2,D1},[2]}, 541: {{D2,D4},[5]},{{D3,D2},[3]},{{D5,D6},[6]},{{D6,D4},[7]}], 542: S), 543: ?line {ok, _} = eval("(E | m1) + (EE | m1)", 544: [E1,E2,E3,E4,E5,E6,E7,{F1,F1},{F3,F1},{F3,F4},{F5,F4}], 545: S), 546: ?line {ok, _} = eval("(Lin)(E | m1)", 547: [{E4,[4]},{E1,[1]},{E2,[2]},{E5,[5]}, 548: {E3,[3]},{E7,[7]},{E6,[6]}], S), 549: ?line {ok, _} = eval("(ELin)(EE | m1)", 550: [{{F1,F1},[1]},{{F1,F4},[1,4]},{{F3,F1},[3]},{{F3,F4},[3]}, 551: {{F5,F4},[6]}], S), 552: ?line {ok, _} = eval("(Lin)(E | m1) + (ELin)(EE | m1)", 553: [{E4,[1,4]},{E1,[1]},{E2,[2]},{E5,[5]}, 554: {E3,[3]},{E7,[7]},{E6,[6]}, 555: {{F1,F1},[1]},{{F3,F1},[3]},{{F3,F4},[3]}, 556: {{F5,F4},[6]}], S), 557: ?line {ok, _} = eval("(Lin)(E | m1) - (ELin)(EE | m1)", 558: [{E1,[1]},{E2,[2]},{E5,[5]}, 559: {E3,[3]},{E7,[7]},{E6,[6]}], S), 560: ?line {ok, _} = eval("(Lin)(E | m1) * (ELin)(EE | m1)", 561: [{E4,[4]}], S), 562: ?line {ok, _} = eval("(XXL)(Lin) (E | m1)", 563: [{{D1,D4},[4]},{{D1,D2},[1]},{{D2,D1},[2]},{{D2,D4},[5]}, 564: {{D3,D2},[3]},{{D6,D4},[7]},{{D5,D6},[6]}], S), 565: ?line {ok, _} = eval("(XXL)(ELin) (EE | m1)", 566: [{{D1,D1},[1]},{{D1,D4},[1,4]},{{D3,D1},[3]},{{D3,D4},[3]}, 567: {{D5,D4},[6]}], S), 568: ?line {ok, _} = eval("(XXL)(Lin)(Fun)(Lin) (E | m1)", 569: [{{D1,D4},[4]},{{D1,D2},[1]},{{D2,D1},[2]},{{D2,D4},[5]}, 570: {{D3,D2},[3]},{{D6,D4},[7]},{{D5,D6},[6]}], S), 571: ?line {ok, _} = eval("(XXL)(ELin)(Fun)(ELin) (EE | m1)", 572: [{{D1,D1},[1]},{{D1,D4},[1,4]},{{D3,D1},[3]},{{D3,D4},[3]}, 573: {{D5,D4},[6]}], S), 574: 575: %% A few tests on regexp. 576: ?line {ok, _} = eval("\"(foo\":Mod", parse_error, S), 577: ?line {ok, _} = eval("_Foo:_/_", parse_error, S), 578: ?line {ok, _} = eval("\".*foo\"", parse_error, S), 579: ?line {ok, _} = eval("_:_/_:Lin", parse_error, S), 580: ?line {ok, _} = eval("_:_/_:Mod", parse_error, S), 581: ?line {ok, _} = eval("_:_/_:App", parse_error, S), 582: ?line {ok, _} = eval("_:_/_:Rel", parse_error, S), 583: ?line {ok, _} = eval("m2:_/4", [F4], S), 584: ?line {ok, _} = eval("m2:_/4:Fun", [F4], S), 585: ?line {ok, _} = eval("\"m.?\":\"f.*\"/\"6\"", [F6], S), 586: ?line {ok, _} = eval("_:_/6", [F6], S), 587: ?line {ok, _} = eval("m1:\"f1\"/_", [F1], S), 588: ?line {ok, _} = eval("\"m1\":f1/_", [F1], S), 589: ?line {ok, _} = eval("\"m1\":Mod", [m1], S), 590: ?line {ok, _} = eval("\"a1\":App", [a1], S), 591: ?line {ok, _} = eval("\"r1\":Rel", [r1], S), 592: ?line {ok, _} = eval("_:_/-1", [], S), 593: 594: ok. 595: 596: loops(suite) -> []; 597: loops(doc) -> ["More Inter Call Graph, loops and \"unusual\" cases"]; 598: loops(Conf) when is_list(Conf) -> 599: S0 = new(), 600: 601: F1 = {m1,f1,1}, % X 602: F2 = {m1,f2,2}, 603: F3 = {m1,f3,3}, % X 604: F4 = {m1,f4,4}, 605: F5 = {m1,f5,5}, 606: F6 = {m1,f1,6}, % X 607: F7 = {m1,f1,7}, 608: 609: E1 = {F1,F1}, % X 610: E2 = {F2,F2}, 611: E3 = {F3,F4}, 612: E4 = {F4,F5}, 613: E5 = {F5,F3}, % X 614: 615: D1 = {F1,1}, 616: D2 = {F2,2}, 617: D3 = {F3,3}, 618: D4 = {F4,4}, 619: D5 = {F5,5}, 620: D6 = {F6,6}, 621: D7 = {F7,7}, 622: DefAt_m1 = [D1,D2,D3,D4,D5,D6,D7], 623: X_m1 = [F1,F3,F6], 624: % L_m1 = [F2,F4,F5], 625: XC_m1 = [], 626: LC_m1 = [E1,E2,E3,E4,E5], 627: LCallAt_m1 = [{E2,2},{E3,3},{E4,4}], 628: XCallAt_m1 = [{E1,1},{E5,5}], 629: Info1 = #xref_mod{name = m1, app_name = [a1]}, 630: ?line S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, 631: XC_m1, LC_m1), 632: 633: ?line S = set_up(S1), 634: 635: % Neither F6 nor F7 is included. Perhaps one should change that? 636: ?line {ok, _} = eval("EE | m1", [E1,E2,{F3,F3}], S), 637: ?line {ok, _} = eval(f("(XXL)(ELin) (EE | ~p)", [F3]), [{{D3,D3},[3]}], S), 638: 639: ?line {ok, _} = eval("m1->m1 | m1->m1", type_error, S), 640: ?line {ok, _} = eval(f("~p | ~p", [F2, F1]), type_error, S), 641: 642: ?line {ok, _} = eval(f("range (closure EE | ~p)", [F1]), [F1], S), 643: ?line {ok, _} = eval(f("domain (closure EE || ~p)", [F3]), [F3], S), 644: 645: ?line {ok, _} = eval(f("domain (closure E || ~p)", [F3]), [F3,F4,F5], S), 646: 647: ?line {ok, _} = eval("components E", [[F1],[F2],[F3,F4,F5]], S), 648: ?line {ok, _} = eval("components EE", [[F1],[F2],[F3]], S), 649: 650: ok. 651: 652: no_data(suite) -> []; 653: no_data(doc) -> ["Simple tests when there is no data"]; 654: no_data(Conf) when is_list(Conf) -> 655: S0 = new(), 656: ?line S1 = set_up(S0), 657: ?line {ok, _} = eval("M", [], S1), 658: ?line {ok, _} = eval("A", [], S1), 659: ?line {ok, _} = eval("R", [], S1), 660: 661: ModInfo = #xref_mod{name = m, app_name = []}, 662: ?line S2 = add_module(S1, ModInfo, [], [], [], [], [], []), 663: AppInfo = #xref_app{name = a, rel_name = []}, 664: ?line S3 = add_application(S2, AppInfo), 665: RelInfo = #xref_rel{name = r, dir = ""}, 666: ?line S4 = add_release(S3, RelInfo), 667: ?line S5 = set_up(S4), 668: ?line {ok, _} = eval("M", [m], S5), 669: ?line {ok, _} = eval("A", [a], S5), 670: ?line {ok, _} = eval("R", [r], S5), 671: ok. 672: 673: modules(suite) -> []; 674: modules(doc) -> ["Modules mode"]; 675: modules(Conf) when is_list(Conf) -> 676: CopyDir = ?copydir, 677: Dir = fname(CopyDir, "rel2"), 678: X = fname(Dir, "x.erl"), 679: Y = fname(Dir, "y.erl"), 680: A1_1 = fname([Dir,"lib","app1-1.1"]), 681: A2 = fname([Dir,"lib","app2-1.1"]), 682: EB1_1 = fname(A1_1, "ebin"), 683: EB2 = fname(A2, "ebin"), 684: Xbeam = fname(EB2, "x.beam"), 685: Ybeam = fname(EB1_1, "y.beam"), 686: 687: ?line {ok, x} = compile:file(X, [debug_info, {outdir,EB2}]), 688: ?line {ok, y} = compile:file(Y, [debug_info, {outdir,EB1_1}]), 689: 690: ?line {ok, S0} = xref_base:new([{xref_mode, modules}]), 691: ?line {ok, release2, S1} = 692: xref_base:add_release(S0, Dir, [{name,release2}]), 693: ?line S = set_up(S1), 694: ?line {{error, _, {unavailable_analysis, undefined_function_calls}}, _} = 695: xref_base:analyze(S, undefined_function_calls), 696: ?line {{error, _, {unavailable_analysis, locals_not_used}}, _} = 697: xref_base:analyze(S, locals_not_used), 698: ?line {{error, _, {unavailable_analysis, {call, foo}}}, _} = 699: xref_base:analyze(S, {call, foo}), 700: ?line {{error, _, {unavailable_analysis, {use, foo}}}, _} = 701: xref_base:analyze(S, {use, foo}), 702: ?line analyze(undefined_functions, [{x,undef,0}], S), 703: ?line 5 = length(xref_base:info(S)), 704: 705: %% More: all info, conversions. 706: 707: ?line ok = file:delete(Xbeam), 708: ?line ok = file:delete(Ybeam), 709: ?line ok = xref_base:delete(S), 710: ok. 711: 712: 713: add(suite) -> []; 714: add(doc) -> ["Add modules, applications, releases, directories"]; 715: add(Conf) when is_list(Conf) -> 716: CopyDir = ?copydir, 717: Dir = fname(CopyDir, "rel2"), 718: UDir = fname([CopyDir,"dir","unreadable"]), 719: DDir = fname(CopyDir,"dir"), 720: UFile = fname([DDir, "dir","unreadable.beam"]), 721: X = fname(Dir, "x.erl"), 722: Y = fname(Dir, "y.erl"), 723: A1_1 = fname([Dir,"lib","app1-1.1"]), 724: A2 = fname([Dir,"lib","app2-1.1"]), 725: EB1_1 = fname(A1_1, "ebin"), 726: EB2 = fname(A2, "ebin"), 727: Xbeam = fname(EB2, "x.beam"), 728: Ybeam = fname(EB1_1, "y.beam"), 729: 730: ?line {ok, x} = compile:file(X, [debug_info, {outdir,EB2}]), 731: ?line {ok, y} = compile:file(Y, [debug_info, {outdir,EB1_1}]), 732: 733: ?line case os:type() of 734: {unix, _} -> 735: ?line make_udir(UDir), 736: ?line make_ufile(UFile); 737: _ -> 738: true 739: end, 740: 741: ?line {error, _, {invalid_options,[not_an_option] }} = 742: xref_base:new([not_an_option]), 743: ?line {error, _, {invalid_options,[{verbose,not_a_value}] }} = 744: xref_base:new([{verbose,not_a_value}]), 745: ?line S = new(), 746: ?line {error, _, {invalid_options,[not_an_option]}} = 747: xref_base:set_up(S, [not_an_option]), 748: ?line {error, _, {invalid_options,[{builtins,true},not_an_option]}} = 749: xref_base:add_directory(S, foo, [{builtins,true},not_an_option]), 750: ?line {error, _, {invalid_options,[{builtins,not_a_value}]}} = 751: xref_base:add_directory(S, foo, [{builtins,not_a_value}]), 752: ?line {error, _, {invalid_filename,{foo,bar}}} = 753: xref_base:add_directory(S, {foo,bar}, []), 754: ?line {error, _, {invalid_options,[{builtins,true},not_an_option]}} = 755: xref_base:add_module(S, foo, [{builtins,true},not_an_option]), 756: ?line {error, _, {invalid_options,[{builtins,not_a_value}]}} = 757: xref_base:add_module(S, foo, [{builtins,not_a_value}]), 758: ?line {error, _, {invalid_filename,{foo,bar}}} = 759: xref_base:add_module(S, {foo,bar}, []), 760: ?line {error, _, {invalid_options,[{builtins,true},not_an_option]}} = 761: xref_base:add_application(S, foo, [{builtins,true},not_an_option]), 762: ?line {error, _, {invalid_options,[{builtins,not_a_value}]}} = 763: xref_base:add_application(S, foo, [{builtins,not_a_value}]), 764: ?line {error, _, {invalid_filename,{foo,bar}}} = 765: xref_base:add_application(S, {foo,bar}, []), 766: ?line {error, _, {invalid_options,[not_an_option]}} = 767: xref_base:add_release(S, foo, [not_an_option]), 768: ?line {error, _, {invalid_options,[{builtins,not_a_value}]}} = 769: xref_base:add_release(S, foo, [{builtins,not_a_value}]), 770: ?line {error, _, {invalid_filename,{foo,bar}}} = 771: xref_base:add_release(S, {foo,bar}, []), 772: ?line {ok, S1} = 773: xref_base:set_default(S, [{verbose,false}, {warnings, false}]), 774: ?line case os:type() of 775: {unix, _} -> 776: ?line {error, _, {file_error, _, _}} = 777: xref_base:add_release(S, UDir); 778: _ -> 779: true 780: end, 781: ?line {error, _, {file_error, _, _}} = 782: xref_base:add_release(S, fname(["/a/b/c/d/e/f","__foo"])), 783: ?line {ok, release2, S2} = 784: xref_base:add_release(S1, Dir, [{name,release2}]), 785: ?line {error, _, {module_clash, {x, _, _}}} = 786: xref_base:add_module(S2, Xbeam), 787: ?line {ok, S3} = xref_base:remove_release(S2, release2), 788: ?line {ok, rel2, S4} = xref_base:add_release(S3, Dir), 789: ?line {error, _, {release_clash, {rel2, _, _}}} = 790: xref_base:add_release(S4, Dir), 791: ?line {ok, S5} = xref_base:remove_release(S4, rel2), 792: %% One unreadable file and one JAM file found (no verification here): 793: ?line {ok, [], S6} = xref_base:add_directory(S5, fname(CopyDir,"dir"), 794: [{recurse,true}, {warnings,true}]), 795: ?line case os:type() of 796: {unix, _} -> 797: ?line {error, _, {file_error, _, _}} = 798: xref_base:add_directory(S6, UDir); 799: _ -> 800: true 801: end, 802: ?line {ok, app1, S7} = xref_base:add_application(S6, A1_1), 803: ?line {error, _, {application_clash, {app1, _, _}}} = 804: xref_base:add_application(S7, A1_1), 805: ?line {ok, S8} = xref_base:remove_application(S7, app1), 806: ?line ok = xref_base:delete(S8), 807: ?line ok = file:delete(Xbeam), 808: ?line ok = file:delete(Ybeam), 809: ?line case os:type() of 810: {unix, _} -> 811: ?line ok = file:del_dir(UDir), 812: ?line ok = file:delete(UFile); 813: _ -> 814: true 815: end, 816: ok. 817: 818: default(suite) -> []; 819: default(doc) -> ["Default values of options"]; 820: default(Conf) when is_list(Conf) -> 821: S = new(), 822: ?line {error, _, {invalid_options,[not_an_option]}} = 823: xref_base:set_default(S, not_an_option, true), 824: ?line {error, _, {invalid_options,[{builtins, not_a_value}]}} = 825: xref_base:set_default(S, builtins, not_a_value), 826: ?line {error, _, {invalid_options,[not_an_option]}} = 827: xref_base:get_default(S, not_an_option), 828: ?line {error, _, {invalid_options,[not_an_option]}} = 829: xref_base:set_default(S, [not_an_option]), 830: 831: ?line D = xref_base:get_default(S), 832: ?line [{builtins,false},{recurse,false},{verbose,false},{warnings,true}] = 833: D, 834: 835: ?line ok = xref_base:delete(S), 836: ok. 837: 838: info(suite) -> []; 839: info(doc) -> ["The info functions"]; 840: info(Conf) when is_list(Conf) -> 841: CopyDir = ?copydir, 842: Dir = fname(CopyDir,"rel2"), 843: LDir = fname(CopyDir,"lib_test"), 844: X = fname(Dir, "x.erl"), 845: Y = fname(Dir, "y.erl"), 846: A1_1 = fname([Dir,"lib","app1-1.1"]), 847: A2 = fname([Dir,"lib","app2-1.1"]), 848: EB1_1 = fname(A1_1, "ebin"), 849: EB2 = fname(A2, "ebin"), 850: Xbeam = fname(EB2, "x.beam"), 851: Ybeam = fname(EB1_1, "y.beam"), 852: 853: ?line {ok, x} = compile:file(X, [debug_info, {outdir,EB2}]), 854: ?line {ok, y} = compile:file(Y, [debug_info, {outdir,EB1_1}]), 855: 856: ?line {ok, _} = start(s), 857: ?line {error, _, {no_such_info, release}} = xref:info(s, release), 858: ?line {error, _, {no_such_info, release}} = xref:info(s, release, rel), 859: ?line {error, _, {no_such_module, mod}} = xref:info(s, modules, mod), 860: ?line {error, _, {no_such_application, app}} = 861: xref:info(s, applications, app), 862: ?line {error, _, {no_such_release, rel}} = xref:info(s, releases, rel), 863: ?line ok = xref:set_default(s, [{verbose,false}, {warnings, false}]), 864: ?line {ok, rel2} = xref:add_release(s, Dir), 865: ?line 9 = length(xref:info(s)), 866: ?line [{x,_}, {y, _}] = xref:info(s, modules), 867: ?line [{app1,_}, {app2, _}] = xref:info(s, applications), 868: ?line [{rel2,_}] = xref:info(s, releases), 869: ?line [] = xref:info(s, libraries), 870: ?line [{x,_}] = xref:info(s, modules, x), 871: ?line [{rel2,_}] = xref:info(s, releases, rel2), 872: ?line {error, _, {no_such_library, foo}} = xref:info(s, libraries, [foo]), 873: 874: ?line {ok, lib1} = 875: compile:file(fname(LDir,lib1),[debug_info,{outdir,LDir}]), 876: ?line {ok, lib2} = 877: compile:file(fname(LDir,lib2),[debug_info,{outdir,LDir}]), 878: ?line ok = xref:set_library_path(s, [LDir], [{verbose,false}]), 879: ?line [{lib1,_}, {lib2, _}] = xref:info(s, libraries), 880: ?line [{lib1,_}, {lib2, _}] = xref:info(s, libraries, [lib1,lib2]), 881: ?line ok = file:delete(fname(LDir, "lib1.beam")), 882: ?line ok = file:delete(fname(LDir, "lib2.beam")), 883: 884: ?line check_state(s), 885: 886: ?line xref:stop(s), 887: 888: ?line ok = file:delete(Xbeam), 889: ?line ok = file:delete(Ybeam), 890: 891: ok. 892: 893: lib(suite) -> []; 894: lib(doc) -> ["Library modules"]; 895: lib(Conf) when is_list(Conf) -> 896: CopyDir = ?copydir, 897: Dir = fname(CopyDir,"lib_test"), 898: UDir = fname([CopyDir,"dir","non_existent"]), 899: 900: ?line {ok, lib1} = compile:file(fname(Dir,lib1),[debug_info,{outdir,Dir}]), 901: ?line {ok, lib2} = compile:file(fname(Dir,lib2),[debug_info,{outdir,Dir}]), 902: ?line {ok, lib3} = compile:file(fname(Dir,lib3),[debug_info,{outdir,Dir}]), 903: ?line {ok, t} = compile:file(fname(Dir,t),[debug_info,{outdir,Dir}]), 904: 905: ?line {ok, _} = start(s), 906: ?line ok = xref:set_default(s, [{verbose,false}, {warnings, false}]), 907: ?line {ok, t} = xref:add_module(s, fname(Dir,"t.beam")), 908: ?line {error, _, {invalid_options,[not_an_option]}} = 909: xref:set_library_path(s, ["foo"], [not_an_option]), 910: ?line {error, _, {invalid_path,otp}} = xref:set_library_path(s,otp), 911: ?line {error, _, {invalid_path,[""]}} = xref:set_library_path(s,[""]), 912: ?line {error, _, {invalid_path,[[$a | $b]]}} = 913: xref:set_library_path(s,[[$a | $b]]), 914: ?line {error, _, {invalid_path,[otp]}} = xref:set_library_path(s,[otp]), 915: ?line {ok, []} = xref:get_library_path(s), 916: ?line ok = xref:set_library_path(s, [Dir], [{verbose,false}]), 917: ?line {ok, UnknownFunctions} = xref:q(s, "U"), 918: ?line [{lib1,unknown,0}, {lib2,local,0}, 919: {lib2,unknown,0}, {unknown,unknown,0}] 920: = UnknownFunctions, 921: ?line {ok, [{lib2,f,0},{lib3,f,0}]} = xref:q(s, "DF"), 922: ?line {ok, []} = xref:q(s, "DF_1"), 923: ?line {ok, [{lib2,f,0}]} = xref:q(s, "DF_2"), 924: ?line {ok, [{lib2,f,0}]} = xref:q(s, "DF_3"), 925: 926: ?line {ok, [unknown]} = xref:q(s, "UM"), 927: ?line {ok, UnknownDefAt} = xref:q(s, "(Lin)U"), 928: ?line [{{lib1,unknown,0},0},{{lib2,local,0},0}, {{lib2,unknown,0},0}, 929: {{unknown,unknown,0},0}] = UnknownDefAt, 930: ?line {ok, LibFuns} = xref:q(s, "X * LM"), 931: ?line [{lib2,f,0},{lib3,f,0}] = LibFuns, 932: ?line {ok, LibMods} = xref:q(s, "LM"), 933: ?line [lib1,lib2,lib3] = LibMods, 934: ?line {ok, [{{lib2,f,0},0},{{lib3,f,0},0}]} = xref:q(s, "(Lin) (LM * X)"), 935: ?line {ok, [{{lib1,unknown,0},0}, {{lib2,f,0},0}, {{lib2,local,0},0}, 936: {{lib2,unknown,0},0}, {{lib3,f,0},0}]} = xref:q(s,"(Lin)LM"), 937: ?line {ok,[lib1,lib2,lib3,t,unknown]} = xref:q(s,"M"), 938: ?line {ok,[{lib2,f,0},{lib3,f,0},{t,t,0}]} = xref:q(s,"X * M"), 939: ?line check_state(s), 940: 941: ?line copy_file(fname(Dir, "lib1.erl"), fname(Dir,"lib1.beam")), 942: ?line ok = xref:set_library_path(s, [Dir]), 943: ?line {error, _, _} = xref:q(s, "U"), 944: 945: %% OTP-3921. AM and LM not always disjoint. 946: ?line {ok, lib1} = compile:file(fname(Dir,lib1),[debug_info,{outdir,Dir}]), 947: ?line {ok, lib1} = xref:add_module(s, fname(Dir,"lib1.beam")), 948: ?line check_state(s), 949: 950: ?line {error, _, {file_error, _, _}} = xref:set_library_path(s, [UDir]), 951: 952: ?line xref:stop(s), 953: ?line ok = file:delete(fname(Dir, "lib1.beam")), 954: ?line ok = file:delete(fname(Dir, "lib2.beam")), 955: ?line ok = file:delete(fname(Dir, "lib3.beam")), 956: ?line ok = file:delete(fname(Dir, "t.beam")), 957: 958: ?line {ok, cp} = compile:file(fname(Dir,cp),[debug_info,{outdir,Dir}]), 959: ?line {ok, _} = start(s), 960: ?line ok = xref:set_default(s, [{verbose,false}, {warnings, false}]), 961: ?line {ok, cp} = xref:add_module(s, fname(Dir,"cp.beam")), 962: ?line {ok, [{lists, sort, 1}]} = xref:q(s, "U"), 963: ?line ok = xref:set_library_path(s, code_path), 964: ?line {ok, []} = xref:q(s, "U"), 965: ?line check_state(s), 966: ?line xref:stop(s), 967: ?line ok = file:delete(fname(Dir, "cp.beam")), 968: ok. 969: 970: read(suite) -> []; 971: read(doc) -> ["Data read from the Abstract Code"]; 972: read(Conf) when is_list(Conf) -> 973: CopyDir = ?copydir, 974: Dir = fname(CopyDir,"read"), 975: File = fname(Dir, "read"), 976: Beam = fname(Dir, "read.beam"), 977: ?line {ok, read} = compile:file(File, [debug_info,{outdir,Dir}]), 978: ?line do_read(File, abstract_v2), 979: ?line copy_file(fname(Dir, "read.beam.v1"), Beam), 980: ?line do_read(File, abstract_v1), 981: ?line ok = file:delete(Beam), 982: ok. 983: 984: do_read(File, Version) -> 985: ?line {ok, _} = start(s), 986: ?line ok = xref:set_default(s, [{verbose,false}, {warnings, false}]), 987: ?line {ok, read} = xref:add_module(s, File), 988: 989: ?line {U, OK, OKB} = read_expected(Version), 990: 991: %% {ok, UC} = xref:q(s, "(Lin) UC"), 992: %% RR = to_external(converse(family_to_relation(family(UC)))), 993: %% lists:foreach(fun(X) -> io:format("~w~n", [X]) end, RR), 994: Unres = to_external(relation_to_family(converse(from_term(U)))), 995: ?line {ok, Unres} = xref:q(s, "(Lin) UC"), 996: 997: %% {ok, EE} = xref:q(s, "(Lin) (E - UC)"), 998: %% AA = to_external(converse(family_to_relation(family(EE)))), 999: %% lists:foreach(fun(X) -> io:format("~w~n", [X]) end, AA), 1000: Calls = to_external(relation_to_family(converse(from_term(OK)))), 1001: ?line {ok, Calls} = xref:q(s, "(Lin) (E - UC) "), 1002: 1003: ?line ok = check_state(s), 1004: ?line {ok, UM} = xref:q(s, "UM"), 1005: ?line true = member('$M_EXPR', UM), 1006: 1007: ?line {ok, X} = xref:q(s, "X"), 1008: ?line true = member({read, module_info, 0}, X), 1009: ?line false = member({foo, module_info, 0}, X), 1010: ?line false = member({erlang, module_info, 0}, X), 1011: ?line {ok, Unknowns} = xref:q(s, "U"), 1012: ?line false = member({read, module_info, 0}, Unknowns), 1013: ?line true = member({foo, module_info, 0}, Unknowns), 1014: ?line true = member({erlang, module_info, 0}, Unknowns), 1015: ?line {ok, LC} = xref:q(s, "LC"), 1016: ?line true = member({{read,bi,0},{read,bi,0}}, LC), 1017: 1018: ?line ok = xref:set_library_path(s, add_erts_code_path(fname(code:lib_dir(kernel),ebin))), 1019: ?line io:format("~p~n",[(catch xref:get_library_path(s))]), 1020: ?line {ok, X2} = xref:q(s, "X"), 1021: ?line ok = check_state(s), 1022: ?line true = member({read, module_info, 0}, X2), 1023: ?line false = member({foo, module_info, 0}, X2), 1024: ?line true = member({erlang, module_info, 0}, X2), 1025: ?line {ok, Unknowns2} = xref:q(s, "U"), 1026: ?line false = member({read, module_info, 0}, Unknowns2), 1027: ?line true = member({foo, module_info, 0}, Unknowns2), 1028: ?line false = member({erlang, module_info, 0}, Unknowns2), 1029: 1030: ?line ok = xref:remove_module(s, read), 1031: ?line {ok, read} = xref:add_module(s, File, [{builtins,true}]), 1032: 1033: UnresB = to_external(relation_to_family(converse(from_term(U)))), 1034: ?line {ok, UnresB} = xref:q(s, "(Lin) UC"), 1035: CallsB = to_external(relation_to_family(converse(from_term(OKB)))), 1036: ?line {ok, CallsB} = xref:q(s, "(Lin) (E - UC) "), 1037: ?line ok = check_state(s), 1038: ?line {ok, XU} = xref:q(s, "XU"), 1039: ?line Erl = set([{erlang,length,1},{erlang,integer,1}, 1040: {erlang,binary_to_term,1}]), 1041: ?line [{erlang,binary_to_term,1},{erlang,length,1}] = 1042: to_external(intersection(set(XU), Erl)), 1043: ?line xref:stop(s). 1044: 1045: %% What is expected when xref_SUITE_data/read/read.erl is added: 1046: read_expected(Version) -> 1047: %% Line positions in xref_SUITE_data/read/read.erl: 1048: POS1 = 28, POS2 = POS1+10, POS3 = POS2+6, POS4 = POS3+6, POS5 = POS4+10, 1049: POS6 = POS5+5, POS7 = POS6+6, POS8 = POS7+6, POS9 = POS8+8, 1050: POS10 = POS9+10, POS11 = POS10+7, POS12 = POS11+8, POS13 = POS12+10, 1051: POS14 = POS13+18, % POS15 = POS14+23, 1052: 1053: FF = {read,funfuns,0}, 1054: U = [{POS1+5,{FF,{dist,'$F_EXPR',0}}}, 1055: {POS1+8,{FF,{dist,'$F_EXPR',0}}}, 1056: {POS2+8,{{read,funfuns,0},{expr,'$F_EXPR',1}}}, 1057: {POS3+4,{FF,{expr,'$F_EXPR',2}}}, 1058: {POS4+2,{FF,{modul,'$F_EXPR',1}}}, 1059: {POS4+4,{FF,{spm,'$F_EXPR',1}}}, 1060: {POS4+6,{FF,{spm,'$F_EXPR',1}}}, 1061: {POS4+8,{FF,{spm,'$F_EXPR',1}}}, 1062: {POS5+1,{FF,{'$M_EXPR','$F_EXPR',0}}}, 1063: {POS5+2,{FF,{'$M_EXPR','$F_EXPR',0}}}, 1064: {POS5+3,{FF,{'$M_EXPR','$F_EXPR',0}}}, 1065: {POS6+1,{FF,{'$M_EXPR','$F_EXPR',0}}}, 1066: {POS6+2,{FF,{'$M_EXPR','$F_EXPR',0}}}, 1067: {POS6+4,{FF,{n,'$F_EXPR',-1}}}, 1068: {POS7+1,{FF,{'$M_EXPR',f,1}}}, 1069: {POS7+2,{FF,{'$M_EXPR',f,1}}}, 1070: {POS8+2,{FF,{hej,'$F_EXPR',1}}}, 1071: {POS8+3,{FF,{t,'$F_EXPR',1}}}, 1072: {POS8+5,{FF,{a,'$F_EXPR',1}}}, 1073: {POS8+7,{FF,{m,'$F_EXPR',1}}}, 1074: {POS9+1,{FF,{'$M_EXPR',f,1}}}, 1075: {POS9+3,{FF,{a,'$F_EXPR',1}}}, 1076: {POS10+1,{FF,{'$M_EXPR',foo,1}}}, 1077: {POS10+2,{FF,{'$M_EXPR','$F_EXPR',1}}}, 1078: {POS10+3,{FF,{'$M_EXPR','$F_EXPR',2}}}, 1079: {POS10+4,{FF,{'$M_EXPR','$F_EXPR',1}}}, 1080: {POS10+5,{FF,{'$M_EXPR',san,1}}}, 1081: {POS10+6,{FF,{'$M_EXPR','$F_EXPR',1}}}, 1082: {POS11+1,{FF,{'$M_EXPR','$F_EXPR',1}}}, 1083: {POS11+2,{FF,{'$M_EXPR','$F_EXPR',-1}}}, 1084: {POS11+3,{FF,{m,f,-1}}}, 1085: {POS11+4,{FF,{m,f,-1}}}, 1086: {POS11+5,{FF,{'$M_EXPR','$F_EXPR',1}}}, 1087: {POS11+6,{FF,{'$M_EXPR','$F_EXPR',1}}}, 1088: {POS12+1,{FF,{'$M_EXPR','$F_EXPR',-1}}}, 1089: {POS12+4,{FF,{'$M_EXPR','$F_EXPR',2}}}, 1090: {POS12+7,{FF,{'$M_EXPR','$F_EXPR',-1}}}, 1091: {POS12+8,{FF,{m4,f4,-1}}}, 1092: {POS13+2,{FF,{debug,'$F_EXPR',0}}}, 1093: {POS13+3,{FF,{'$M_EXPR','$F_EXPR',-1}}}, 1094: {POS14+8,{{read,bi,0},{'$M_EXPR','$F_EXPR',1}}}], 1095: 1096: O1 = [{20,{{read,lc,0},{ets,new,0}}}, 1097: {21,{{read,lc,0},{ets,tab2list,1}}}, 1098: {POS1+1,{FF,{erlang,spawn,1}}}, 1099: {POS1+1,{FF,{mod17,fun17,0}}}, 1100: {POS1+2,{FF,{erlang,spawn,1}}}, 1101: {POS1+2,{FF,{read,local,0}}}, 1102: {POS1+3,{FF,{erlang,spawn,1}}}, 1103: {POS1+4,{FF,{dist,func,0}}}, 1104: {POS1+4,{FF,{erlang,spawn,1}}}, 1105: {POS1+5,{FF,{erlang,spawn,1}}}, 1106: {POS1+6,{FF,{erlang,spawn_link,1}}}, 1107: {POS1+6,{FF,{mod17,fun17,0}}}, 1108: {POS1+7,{FF,{dist,func,0}}}, 1109: {POS1+7,{FF,{erlang,spawn_link,1}}}, 1110: {POS1+8,{FF,{erlang,spawn_link,1}}}, 1111: {POS2+1,{FF,{d,f,0}}}, 1112: {POS2+1,{FF,{dist,func,2}}}, 1113: {POS2+1,{FF,{erlang,spawn,2}}}, 1114: {POS2+2,{FF,{dist,func,2}}}, 1115: {POS2+2,{FF,{erlang,spawn,2}}}, 1116: {POS2+2,{FF,{mod42,func,0}}}, 1117: {POS2+3,{FF,{d,f,0}}}, 1118: {POS2+3,{FF,{dist,func,2}}}, 1119: {POS2+3,{FF,{erlang,spawn_link,2}}}, 1120: {POS2+4,{FF,{dist,func,2}}}, 1121: {POS2+4,{FF,{erlang,spawn_link,2}}}, 1122: {POS2+4,{FF,{mod42,func,0}}}, 1123: {POS3+1,{FF,{dist,func,2}}}, 1124: {POS3+3,{FF,{dist,func,2}}}, 1125: {POS4+1,{FF,{erlang,spawn,4}}}, 1126: {POS4+1,{FF,{modul,function,0}}}, 1127: {POS4+2,{FF,{erlang,spawn,4}}}, 1128: {POS4+3,{FF,{dist,func,2}}}, 1129: {POS4+3,{FF,{erlang,spawn,4}}}, 1130: {POS4+3,{FF,{spm,spf,2}}}, 1131: {POS4+4,{FF,{dist,func,2}}}, 1132: {POS4+4,{FF,{erlang,spawn,4}}}, 1133: {POS4+5,{FF,{dist,func,2}}}, 1134: {POS4+5,{FF,{erlang,spawn_link,4}}}, 1135: {POS4+5,{FF,{spm,spf,2}}}, 1136: {POS4+6,{FF,{dist,func,2}}}, 1137: {POS4+6,{FF,{erlang,spawn_link,4}}}, 1138: {POS4+7,{FF,{erlang,spawn_opt,4}}}, 1139: {POS4+7,{FF,{read,bi,0}}}, 1140: {POS4+7,{FF,{spm,spf,2}}}, 1141: {POS4+8,{FF,{erlang,spawn_opt,4}}}, 1142: {POS4+8,{FF,{read,bi,0}}}, 1143: {POS5+1,{FF,{erlang,spawn,1}}}, 1144: {POS5+2,{FF,{erlang,spawn,1}}}, 1145: {POS5+3,{FF,{erlang,spawn_link,1}}}, 1146: {POS6+1,{FF,{erlang,spawn,2}}}, 1147: {POS6+2,{FF,{erlang,spawn_link,2}}}, 1148: {POS7+1,{FF,{erlang,spawn,4}}}, 1149: {POS7+2,{FF,{erlang,spawn_opt,4}}}, 1150: {POS8+1,{FF,{hej,san,1}}}, 1151: {POS8+4,{FF,{a,b,1}}}, 1152: {POS8+4,{FF,{erlang,apply,2}}}, 1153: {POS8+5,{FF,{erlang,apply,2}}}, 1154: {POS8+6,{FF,{erlang,apply,3}}}, 1155: {POS8+6,{FF,{m,f,1}}}, 1156: {POS8+7,{FF,{erlang,apply,3}}}, 1157: {POS9+1,{FF,{erlang,apply,3}}}, 1158: {POS9+1,{FF,{read,bi,0}}}, 1159: {POS9+2,{FF,{a,b,1}}}, 1160: {POS9+2,{FF,{erlang,apply,2}}}, 1161: {POS9+3,{FF,{erlang,apply,2}}}, 1162: {POS9+4,{FF,{erlang,apply,2}}}, 1163: {POS9+4,{FF,{erlang,not_a_function,1}}}, 1164: {POS9+5,{FF,{erlang,apply,3}}}, 1165: {POS9+5,{FF,{mod,func,2}}}, 1166: {POS9+6,{FF,{erlang,apply,1}}}, 1167: {POS9+7,{FF,{erlang,apply,2}}}, 1168: {POS9+7,{FF,{math,add3,1}}}, 1169: {POS9+8,{FF,{q,f,1}}}, 1170: {POS10+4,{FF,{erlang,apply,2}}}, 1171: {POS10+5,{FF,{mod1,fun1,1}}}, 1172: {POS11+1,{FF,{erlang,apply,3}}}, 1173: {POS11+2,{FF,{erlang,apply,3}}}, 1174: {POS11+3,{FF,{erlang,apply,3}}}, 1175: {POS11+4,{FF,{erlang,apply,3}}}, 1176: {POS11+6,{FF,{erlang,apply,2}}}, 1177: {POS12+1,{FF,{erlang,apply,2}}}, 1178: {POS12+4,{FF,{erlang,apply,2}}}, 1179: {POS12+5,{FF,{erlang,apply,3}}}, 1180: {POS12+5,{FF,{m3,f3,2}}}, 1181: {POS12+7,{FF,{erlang,apply,2}}}, 1182: {POS12+8,{FF,{erlang,apply,3}}}, 1183: {POS13+1,{FF,{dm,df,1}}}, 1184: {POS13+6,{{read,bi,0},{foo,module_info,0}}}, 1185: {POS13+7,{{read,bi,0},{read,module_info,0}}}, 1186: {POS13+9,{{read,bi,0},{t,foo,1}}}, 1187: {POS14+11,{{read,bi,0},{erlang,module_info,0}}}, 1188: {POS14+17,{{read,bi,0},{read,bi,0}}}], 1189: 1190: OK = case Version of 1191: abstract_v1 -> 1192: [{POS8+3, {FF,{erlang,apply,3}}}, 1193: {POS10+1, {FF,{erlang,apply,3}}}, 1194: {POS10+6, {FF,{erlang,apply,3}}}] 1195: ++ 1196: [{0,{FF,{read,'$F_EXPR',178}}}, 1197: {0,{FF,{modul,'$F_EXPR',179}}}] 1198: ++ O1; 1199: _ -> 1200: % [{POS15+2,{{read,bi,0},{foo,t,0}}}, 1201: % {POS15+3,{{read,bi,0},{bar,t,0}}}, 1202: % {POS15+6,{{read,bi,0},{read,local,0}}}, 1203: % {POS15+8,{{read,bi,0},{foo,t,0}}}, 1204: % {POS15+10,{{read,bi,0},{bar,t,0}}}] ++ 1205: [{16,{FF,{read,'$F_EXPR',178}}}, 1206: {17,{FF,{modul,'$F_EXPR',179}}}] 1207: ++ 1208: O1 1209: end, 1210: 1211: %% When builtins =:= true: 1212: OKB1 = [{POS13+1,{FF,{erts_debug,apply,4}}}, 1213: {POS13+2,{FF,{erts_debug,apply,4}}}, 1214: {POS13+3,{FF,{erts_debug,apply,4}}}, 1215: {POS1+3, {FF,{erlang,binary_to_term,1}}}, 1216: {POS3+1, {FF,{erlang,spawn,3}}}, 1217: {POS3+2, {FF,{erlang,spawn,3}}}, 1218: {POS3+3, {FF,{erlang,spawn_link,3}}}, 1219: {POS3+4, {FF,{erlang,spawn_link,3}}}, 1220: {POS6+4, {FF,{erlang,spawn,3}}}, 1221: {POS13+5, {{read,bi,0},{erlang,length,1}}}, 1222: {POS14+3, {{read,bi,0},{erlang,length,1}}}], 1223: 1224: %% Operators (OTP-8647): 1225: OKB = case Version of 1226: abstract_v1 -> 1227: []; 1228: _ -> 1229: [{POS13+16, {{read,bi,0},{erlang,'!',2}}}, 1230: {POS13+16, {{read,bi,0},{erlang,'-',1}}}, 1231: {POS13+16, {{read,bi,0},{erlang,self,0}}}] 1232: end 1233: ++ [{POS14+19, {{read,bi,0},{erlang,'+',2}}}, 1234: {POS14+21, {{read,bi,0},{erlang,'+',2}}}, 1235: {POS13+16, {{read,bi,0},{erlang,'==',2}}}, 1236: {POS14+15, {{read,bi,0},{erlang,'==',2}}}, 1237: {POS13+5, {{read,bi,0},{erlang,'>',2}}}, 1238: {POS14+3, {{read,bi,0},{erlang,'>',2}}}] 1239: ++ OKB1 ++ OK, 1240: 1241: {U, OK, OKB}. 1242: 1243: read2(suite) -> []; 1244: read2(doc) -> ["Data read from the Abstract Code (cont)"]; 1245: read2(Conf) when is_list(Conf) -> 1246: %% Handles the spawn_opt versions added in R9 (OTP-4180). 1247: %% Expected augmentations: try/catch, cond. 1248: CopyDir = ?copydir, 1249: Dir = fname(CopyDir,"read"), 1250: File = fname(Dir, "read2.erl"), 1251: MFile = fname(Dir, "read2"), 1252: Beam = fname(Dir, "read2.beam"), 1253: Test = <<"-module(read2). 1254: -compile(export_all). 1255: 1256: f() -> 1257: spawn_opt({read2,f}, % POS2 1258: [f()]), 1259: spawn_opt(fun() -> foo end, [link]), 1260: spawn_opt(f(), 1261: {read2,f}, [{min_heap_size,1000}]), 1262: spawn_opt(f(), 1263: fun() -> f() end, [flopp]), 1264: spawn_opt(f(), 1265: read2, f, [], []); 1266: f() -> 1267: %% Duplicated unresolved calls are ignored: 1268: (f())(foo,bar),(f())(foo,bar). % POS1 1269: ">>, 1270: ?line ok = file:write_file(File, Test), 1271: ?line {ok, read2} = compile:file(File, [debug_info,{outdir,Dir}]), 1272: 1273: ?line {ok, _} = xref:start(s), 1274: ?line {ok, read2} = xref:add_module(s, MFile), 1275: ?line {U0, OK0} = read2_expected(), 1276: 1277: U = to_external(relation_to_family(converse(from_term(U0)))), 1278: OK = to_external(relation_to_family(converse(from_term(OK0)))), 1279: ?line {ok, U2} = xref:q(s, "(Lin) UC"), 1280: ?line {ok, OK2} = xref:q(s, "(Lin) (E - UC)"), 1281: ?line true = U =:= U2, 1282: ?line true = OK =:= OK2, 1283: ?line ok = check_state(s), 1284: ?line xref:stop(s), 1285: 1286: ?line ok = file:delete(File), 1287: ?line ok = file:delete(Beam), 1288: ok. 1289: 1290: 1291: read2_expected() -> 1292: POS1 = 16, 1293: POS2 = 5, 1294: FF = {read2,f,0}, 1295: U = [{POS1,{FF,{'$M_EXPR','$F_EXPR',2}}}], 1296: OK = [{POS2,{FF,{erlang,spawn_opt,2}}}, 1297: {POS2,{FF,FF}}, 1298: {POS2+1,{FF,FF}}, 1299: {POS2+2,{FF,{erlang,spawn_opt,2}}}, 1300: {POS2+3,{FF,{erlang,spawn_opt,3}}}, 1301: {POS2+3,{FF,FF}}, 1302: {POS2+3,{FF,FF}}, 1303: {POS2+5,{FF,{erlang,spawn_opt,3}}}, 1304: {POS2+5,{FF,FF}}, 1305: {POS2+6,{FF,FF}}, 1306: {POS2+7,{FF,{erlang,spawn_opt,5}}}, 1307: {POS2+7,{FF,FF}}, 1308: {POS2+7,{FF,FF}}, 1309: {POS1,{FF,FF}}], 1310: {U, OK}. 1311: 1312: remove(suite) -> []; 1313: remove(doc) -> ["Remove modules, applications, releases"]; 1314: remove(Conf) when is_list(Conf) -> 1315: S = new(), 1316: ?line {error, _, {no_such_module, mod}} = 1317: xref_base:remove_module(S, mod), 1318: ?line {error, _, {no_such_application, app}} = 1319: xref_base:remove_application(S, app), 1320: ?line {error, _, {no_such_release, rel}} = 1321: xref_base:remove_release(S, rel), 1322: ?line ok = xref_base:delete(S), 1323: ok. 1324: 1325: replace(suite) -> []; 1326: replace(doc) -> ["Replace modules, applications, releases"]; 1327: replace(Conf) when is_list(Conf) -> 1328: CopyDir = ?copydir, 1329: Dir = fname(CopyDir,"rel2"), 1330: X = fname(Dir, "x.erl"), 1331: Y = fname(Dir, "y.erl"), 1332: A1_0 = fname(Dir, fname("lib","app1-1.0")), 1333: A1_1 = fname(Dir, fname("lib","app1-1.1")), 1334: A2 = fname(Dir, fname("lib","app2-1.1")), 1335: EB1_0 = fname(A1_0, "ebin"), 1336: EB1_1 = fname(A1_1, "ebin"), 1337: Xbeam = fname(EB1_1, "x.beam"), 1338: Ybeam = fname(EB1_1, "y.beam"), 1339: 1340: ?line {ok, x} = compile:file(X, [debug_info, {outdir,EB1_0}]), 1341: ?line {ok, x} = compile:file(X, [debug_info, {outdir,EB1_1}]), 1342: ?line {ok, y} = compile:file(Y, [debug_info, {outdir,EB1_1}]), 1343: 1344: ?line {ok, _} = start(s), 1345: ?line {ok, false} = xref:set_default(s, verbose, false), 1346: ?line {ok, true} = xref:set_default(s, warnings, false), 1347: ?line {ok, rel2} = xref:add_release(s, Dir, []), 1348: ?line {error, _, _} = xref:replace_application(s, app1, "no_data"), 1349: ?line {error, _, {no_such_application, app12}} = 1350: xref:replace_application(s, app12, A1_0, []), 1351: ?line {error, _, {invalid_filename,{foo,bar}}} = 1352: xref:replace_application(s, app1, {foo,bar}, []), 1353: ?line {error, _, {invalid_options,[not_an_option]}} = 1354: xref:replace_application(s, foo, bar, [not_an_option]), 1355: ?line {error, _, {invalid_options,[{builtins,not_a_value}]}} = 1356: xref:replace_application(s, foo, bar, [{builtins,not_a_value}]), 1357: ?line {ok, app1} = 1358: xref:replace_application(s, app1, A1_0), 1359: ?line [{_, AppInfo}] = xref:info(s, applications, app1), 1360: ?line {value, {release, [rel2]}} = keysearch(release, 1, AppInfo), 1361: 1362: ?line {error, _, {no_such_module, xx}} = 1363: xref:replace_module(s, xx, Xbeam, []), 1364: ?line {error, _, {invalid_options,[{builtins,true},not_an_option]}} = 1365: xref:replace_module(s, foo, bar,[{builtins,true},not_an_option]), 1366: ?line {error, _, {invalid_options,[{builtins,not_a_value}]}} = 1367: xref:replace_module(s, foo, bar, [{builtins,not_a_value}]), 1368: ?line {error, _, {invalid_filename,{foo,bar}}} = 1369: xref:replace_module(s, x, {foo,bar}), 1370: ?line {ok, x} = xref:replace_module(s, x, Xbeam), 1371: ?line [{x, ModInfo}] = xref:info(s, modules, x), 1372: ?line {value, {application, [app1]}} = 1373: keysearch(application, 1, ModInfo), 1374: 1375: ?line {ok, x} = compile:file(X, [no_debug_info, {outdir,EB1_1}]), 1376: ?line {error, _, {no_debug_info, _}} = xref:replace_module(s, x, Xbeam), 1377: ?line {error, _, {module_mismatch, x,y}} = 1378: xref:replace_module(s, x, Ybeam), 1379: ?line case os:type() of 1380: {unix, _} -> 1381: ?line hide_file(Ybeam), 1382: ?line {error, _, {file_error, _, _}} = 1383: xref:replace_module(s, x, Ybeam); 1384: _ -> 1385: true 1386: end, 1387: ?line ok = xref:remove_module(s, x), 1388: ?line {error, _, {no_debug_info, _}} = xref:add_module(s, Xbeam), 1389: 1390: %% "app2" is ignored, the old application name is kept 1391: ?line {ok, app1} = xref:replace_application(s, app1, A2), 1392: 1393: ?line xref:stop(s), 1394: ?line ok = file:delete(fname(EB1_0, "x.beam")), 1395: ?line ok = file:delete(Xbeam), 1396: ?line ok = file:delete(Ybeam), 1397: ok. 1398: 1399: update(suite) -> []; 1400: update(doc) -> ["The update() function"]; 1401: update(Conf) when is_list(Conf) -> 1402: CopyDir = ?copydir, 1403: Dir = fname(CopyDir,"update"), 1404: Source = fname(Dir, "x.erl"), 1405: Beam = fname(Dir, "x.beam"), 1406: ?line copy_file(fname(Dir, "x.erl.1"), Source), 1407: ?line {ok, x} = compile:file(Source, [debug_info, {outdir,Dir}]), 1408: 1409: ?line {ok, _} = start(s), 1410: ?line ok = xref:set_default(s, [{verbose,false}, {warnings, false}]), 1411: ?line {ok, [x]} = xref:add_directory(s, Dir, [{builtins,true}]), 1412: ?line {error, _, {invalid_options,[not_an_option]}} = 1413: xref:update(s, [not_an_option]), 1414: ?line {ok, []} = xref:update(s), 1415: ?line {ok, [{erlang,atom_to_list,1}]} = xref:q(s, "XU"), 1416: 1417: ?line [{x, ModInfo}] = xref:info(s, modules, x), 1418: ?line case keysearch(directory, 1, ModInfo) of 1419: {value, {directory, Dir}} -> ok 1420: end, 1421: 1422: timer:sleep(2000), % make sure modification time has changed 1423: ?line copy_file(fname(Dir, "x.erl.2"), Source), 1424: ?line {ok, x} = compile:file(Source, [debug_info, {outdir,Dir}]), 1425: ?line {ok, [x]} = xref:update(s, []), 1426: ?line {ok, [{erlang,list_to_atom,1}]} = xref:q(s, "XU"), 1427: 1428: timer:sleep(2000), 1429: ?line {ok, x} = compile:file(Source, [no_debug_info,{outdir,Dir}]), 1430: ?line {error, _, {no_debug_info, _}} = xref:update(s), 1431: 1432: ?line xref:stop(s), 1433: ?line ok = file:delete(Beam), 1434: ?line ok = file:delete(Source), 1435: ok. 1436: 1437: deprecated(suite) -> []; 1438: deprecated(doc) -> ["OTP-4695: Deprecated functions."]; 1439: deprecated(Conf) when is_list(Conf) -> 1440: Dir = ?copydir, 1441: File = fname(Dir, "depr.erl"), 1442: MFile_r9c = fname(Dir, "depr_r9c"), 1443: MFile = fname(Dir, "depr"), 1444: Beam = fname(Dir, "depr.beam"), 1445: %% This file has been compiled to ?datadir/depr_r9c.beam 1446: %% using the R9C compiler. From R10B and onwards the linter 1447: %% checks the 'deprecated' attribute as well. 1448: % Test = <<"-module(depr). 1449: 1450: % -export([t/0,f/1,bar/2,f/2,g/3]). 1451: 1452: % -deprecated([{f,1}, % DF 1453: % {bar,2,eventually}]). % DF_3 1454: % -deprecated([{f,1,next_major_release}]). % DF_2 (again) 1455: % -deprecated([{frutt,0,next_version}]). % message... 1456: % -deprecated([{f,2,next_major_release}, % DF_2 1457: % {g,3,next_version}, % DF_1 1458: % {ignored,10,100}]). % message... 1459: % -deprecated([{does_not_exist,1}]). % message... 1460: 1461: % -deprecated(foo). % message... 1462: 1463: % t() -> 1464: % frutt(1), 1465: % g(1,2, 3), 1466: % ?MODULE:f(10). 1467: 1468: % f(A) -> 1469: % ?MODULE:f(A,A). 1470: 1471: % f(X, Y) -> 1472: % ?MODULE:g(X, Y, X). 1473: 1474: % g(F, G, H) -> 1475: % ?MODULE:bar(F, {G,H}). 1476: 1477: % bar(_, _) -> 1478: % true. 1479: 1480: % frutt(_) -> 1481: % frutt(). 1482: 1483: % frutt() -> 1484: % true. 1485: % ">>, 1486: 1487: % ?line ok = file:write_file(File, Test), 1488: % ?line {ok, depr_r9c} = compile:file(File, [debug_info,{outdir,Dir}]), 1489: 1490: ?line {ok, _} = xref:start(s), 1491: ?line {ok, depr_r9c} = xref:add_module(s, MFile_r9c), 1492: M9 = depr_r9c, 1493: DF_1 = usort([{{M9,f,2},{M9,g,3}}]), 1494: DF_2 = usort(DF_1++[{{M9,f,1},{M9,f,2}},{{M9,t,0},{M9,f,1}}]), 1495: DF_3 = usort(DF_2++[{{M9,g,3},{M9,bar,2}}]), 1496: DF = usort(DF_3++[{{M9,t,0},{M9,f,1}}]), 1497: 1498: ?line {ok,DF} = xref:analyze(s, deprecated_function_calls), 1499: ?line {ok,DF_1} = 1500: xref:analyze(s, {deprecated_function_calls,next_version}), 1501: ?line {ok,DF_2} = 1502: xref:analyze(s, {deprecated_function_calls,next_major_release}), 1503: ?line {ok,DF_3} = 1504: xref:analyze(s, {deprecated_function_calls,eventually}), 1505: 1506: D = to_external(range(from_term(DF))), 1507: D_1 = to_external(range(from_term(DF_1))), 1508: D_2 = to_external(range(from_term(DF_2))), 1509: D_3 = to_external(range(from_term(DF_3))), 1510: 1511: ?line {ok,D} = xref:analyze(s, deprecated_functions), 1512: ?line {ok,D_1} = 1513: xref:analyze(s, {deprecated_functions,next_version}), 1514: ?line {ok,D_2} = 1515: xref:analyze(s, {deprecated_functions,next_major_release}), 1516: ?line {ok,D_3} = 1517: xref:analyze(s, {deprecated_functions,eventually}), 1518: 1519: ?line ok = check_state(s), 1520: ?line xref:stop(s), 1521: 1522: Test2= <<"-module(depr). 1523: 1524: -export([t/0,f/1,bar/2,f/2,g/3]). 1525: 1526: -deprecated([{'_','_',eventually}]). % DF_3 1527: -deprecated([{f,'_',next_major_release}]). % DF_2 1528: -deprecated([{g,'_',next_version}]). % DF_1 1529: -deprecated([{bar,2}]). % DF 1530: 1531: t() -> 1532: g(1,2, 3), 1533: ?MODULE:f(10). 1534: 1535: f(A) -> 1536: ?MODULE:f(A,A). 1537: 1538: f(X, Y) -> 1539: ?MODULE:g(X, Y, X). 1540: 1541: g(F, G, H) -> 1542: ?MODULE:bar(F, {G,H}). 1543: 1544: bar(_, _) -> 1545: ?MODULE:t(). 1546: ">>, 1547: 1548: ?line ok = file:write_file(File, Test2), 1549: ?line {ok, depr} = compile:file(File, [debug_info,{outdir,Dir}]), 1550: 1551: ?line {ok, _} = xref:start(s), 1552: ?line {ok, depr} = xref:add_module(s, MFile), 1553: 1554: M = depr, 1555: DFa_1 = usort([{{M,f,2},{M,g,3}}]), 1556: DFa_2 = usort(DFa_1++[{{M,f,1},{M,f,2}},{{M,t,0},{M,f,1}}]), 1557: DFa_3 = usort(DFa_2++[{{M,bar,2},{M,t,0}},{{M,g,3},{M,bar,2}}]), 1558: DFa = DFa_3, 1559: 1560: ?line {ok,DFa} = xref:analyze(s, deprecated_function_calls), 1561: ?line {ok,DFa_1} = 1562: xref:analyze(s, {deprecated_function_calls,next_version}), 1563: ?line {ok,DFa_2} = 1564: xref:analyze(s, {deprecated_function_calls,next_major_release}), 1565: ?line {ok,DFa_3} = 1566: xref:analyze(s, {deprecated_function_calls,eventually}), 1567: 1568: ?line ok = check_state(s), 1569: ?line xref:stop(s), 1570: 1571: %% All of the module is deprecated. 1572: Test3= <<"-module(depr). 1573: 1574: -export([t/0,f/1,bar/2,f/2,g/3]). 1575: 1576: -deprecated([{f,'_',next_major_release}]). % DF_2 1577: -deprecated([{g,'_',next_version}]). % DF_1 1578: -deprecated(module). % DF 1579: 1580: t() -> 1581: g(1,2, 3), 1582: ?MODULE:f(10). 1583: 1584: f(A) -> 1585: ?MODULE:f(A,A). 1586: 1587: f(X, Y) -> 1588: ?MODULE:g(X, Y, X). 1589: 1590: g(F, G, H) -> 1591: ?MODULE:bar(F, {G,H}). 1592: 1593: bar(_, _) -> 1594: ?MODULE:t(). 1595: ">>, 1596: 1597: ?line ok = file:write_file(File, Test3), 1598: ?line {ok, depr} = compile:file(File, [debug_info,{outdir,Dir}]), 1599: 1600: ?line {ok, _} = xref:start(s), 1601: ?line {ok, depr} = xref:add_module(s, MFile), 1602: 1603: DFb_1 = usort([{{M,f,2},{M,g,3}}]), 1604: DFb_2 = usort(DFb_1++[{{M,f,1},{M,f,2}},{{M,t,0},{M,f,1}}]), 1605: DFb_3 = DFb_2, 1606: DFb = usort(DFb_2++[{{M,bar,2},{M,t,0}},{{M,g,3},{M,bar,2}}]), 1607: 1608: ?line {ok,DFb} = xref:analyze(s, deprecated_function_calls), 1609: ?line {ok,DFb_1} = 1610: xref:analyze(s, {deprecated_function_calls,next_version}), 1611: ?line {ok,DFb_2} = 1612: xref:analyze(s, {deprecated_function_calls,next_major_release}), 1613: ?line {ok,DFb_3} = 1614: xref:analyze(s, {deprecated_function_calls,eventually}), 1615: 1616: ?line ok = check_state(s), 1617: ?line xref:stop(s), 1618: 1619: ?line ok = file:delete(File), 1620: ?line ok = file:delete(Beam), 1621: ok. 1622: 1623: 1624: trycatch(suite) -> []; 1625: trycatch(doc) -> ["OTP-5152: try/catch, final (?) version."]; 1626: trycatch(Conf) when is_list(Conf) -> 1627: Dir = ?copydir, 1628: File = fname(Dir, "trycatch.erl"), 1629: MFile = fname(Dir, "trycatch"), 1630: Beam = fname(Dir, "trycatch.beam"), 1631: Test = <<"-module(trycatch). 1632: 1633: -export([trycatch/0]). 1634: 1635: trycatch() -> 1636: try 1637: foo:bar(), 1638: bar:foo() of 1639: 1 -> foo:foo(); 1640: 2 -> bar:bar() 1641: catch 1642: error:a -> err:e1(); 1643: error:b -> err:e2() 1644: after 1645: fini:shed() 1646: end. 1647: ">>, 1648: 1649: ?line ok = file:write_file(File, Test), 1650: ?line {ok, trycatch} = compile:file(File, [debug_info,{outdir,Dir}]), 1651: 1652: ?line {ok, _} = xref:start(s), 1653: ?line {ok, trycatch} = xref:add_module(s, MFile), 1654: A = trycatch, 1655: {ok,[{{{A,A,0},{bar,bar,0}},[10]}, 1656: {{{A,A,0},{bar,foo,0}},[8]}, 1657: {{{A,A,0},{err,e1,0}},[12]}, 1658: {{{A,A,0},{err,e2,0}},[13]}, 1659: {{{A,A,0},{fini,shed,0}},[15]}, 1660: {{{A,A,0},{foo,bar,0}},[7]}, 1661: {{{A,A,0},{foo,foo,0}},[9]}]} = 1662: xref:q(s, "(Lin) (E | trycatch:trycatch/0)"), 1663: 1664: ?line ok = check_state(s), 1665: ?line xref:stop(s), 1666: 1667: ?line ok = file:delete(File), 1668: ?line ok = file:delete(Beam), 1669: ok. 1670: 1671: 1672: fun_mfa(suite) -> []; 1673: fun_mfa(doc) -> ["OTP-5653: fun M:F/A."]; 1674: fun_mfa(Conf) when is_list(Conf) -> 1675: Dir = ?copydir, 1676: File = fname(Dir, "fun_mfa.erl"), 1677: MFile = fname(Dir, "fun_mfa"), 1678: Beam = fname(Dir, "fun_mfa.beam"), 1679: Test = <<"-module(fun_mfa). 1680: 1681: -export([t/0, t1/0, t2/0, t3/0]). 1682: 1683: t() -> 1684: F = fun ?MODULE:t/0, 1685: (F)(). 1686: 1687: t1() -> 1688: F = fun t/0, 1689: (F)(). 1690: 1691: t2() -> 1692: fun ?MODULE:t/0(). 1693: 1694: t3() -> 1695: fun t3/0(). 1696: ">>, 1697: 1698: ?line ok = file:write_file(File, Test), 1699: A = fun_mfa, 1700: ?line {ok, A} = compile:file(File, [debug_info,{outdir,Dir}]), 1701: ?line {ok, _} = xref:start(s), 1702: ?line {ok, A} = xref:add_module(s, MFile, {warnings,false}), 1703: ?line {ok, [{{{A,t,0},{'$M_EXPR','$F_EXPR',0}},[7]}, 1704: {{{A,t,0},{A,t,0}},[6]}, 1705: {{{A,t1,0},{'$M_EXPR','$F_EXPR',0}},[11]}, 1706: {{{A,t1,0},{A,t,0}},[10]}, 1707: {{{A,t2,0},{A,t,0}},[14]}, 1708: {{{A,t3,0},{fun_mfa,t3,0}},[17]}]} = 1709: xref:q(s, "(Lin) E"), 1710: 1711: ?line ok = check_state(s), 1712: ?line xref:stop(s), 1713: 1714: ?line ok = file:delete(File), 1715: ?line ok = file:delete(Beam), 1716: ok. 1717: 1718: %% Same as the previous test case, except that we use a BEAM file 1719: %% that was compiled by an R14 compiler to test backward compatibility. 1720: fun_mfa_r14(Conf) when is_list(Conf) -> 1721: Dir = ?config(data_dir, Conf), 1722: MFile = fname(Dir, "fun_mfa_r14"), 1723: 1724: A = fun_mfa_r14, 1725: {ok, _} = xref:start(s), 1726: {ok, A} = xref:add_module(s, MFile, {warnings,false}), 1727: {ok, [{{{A,t,0},{'$M_EXPR','$F_EXPR',0}},[7]}, 1728: {{{A,t,0},{A,t,0}},[6]}, 1729: {{{A,t1,0},{'$M_EXPR','$F_EXPR',0}},[11]}, 1730: {{{A,t1,0},{A,t,0}},[10]}, 1731: {{{A,t2,0},{A,t,0}},[14]}, 1732: {{{A,t3,0},{A,t3,0}},[17]}]} = 1733: xref:q(s, "(Lin) E"), 1734: 1735: ok = check_state(s), 1736: xref:stop(s), 1737: 1738: ok. 1739: 1740: %% fun M:F/A with varibles. 1741: fun_mfa_vars(Conf) when is_list(Conf) -> 1742: Dir = ?copydir, 1743: File = fname(Dir, "fun_mfa_vars.erl"), 1744: MFile = fname(Dir, "fun_mfa_vars"), 1745: Beam = fname(Dir, "fun_mfa_vars.beam"), 1746: Test = <<"-module(fun_mfa_vars). 1747: 1748: -export([t/1, t1/1, t2/3]). 1749: 1750: t(Mod) -> 1751: F = fun Mod:bar/2, 1752: (F)(a, b). 1753: 1754: t1(Name) -> 1755: F = fun ?MODULE:Name/1, 1756: (F)(a). 1757: 1758: t2(Mod, Name, Arity) -> 1759: F = fun Mod:Name/Arity, 1760: (F)(a). 1761: 1762: t3(Arity) -> 1763: F = fun ?MODULE:t/Arity, 1764: (F)(1, 2, 3). 1765: 1766: t4(Mod, Name) -> 1767: F = fun Mod:Name/3, 1768: (F)(a, b, c). 1769: 1770: t5(Mod, Arity) -> 1771: F = fun Mod:t/Arity, 1772: (F)(). 1773: ">>, 1774: 1775: ok = file:write_file(File, Test), 1776: A = fun_mfa_vars, 1777: {ok, A} = compile:file(File, [report,debug_info,{outdir,Dir}]), 1778: {ok, _} = xref:start(s), 1779: {ok, A} = xref:add_module(s, MFile, {warnings,false}), 1780: {ok, [{{{A,t,1},{'$M_EXPR','$F_EXPR',2}},[7]}, 1781: {{{A,t,1},{'$M_EXPR',bar,2}},[6]}, 1782: {{{A,t1,1},{'$M_EXPR','$F_EXPR',1}},[11]}, 1783: {{{A,t1,1},{A,'$F_EXPR',1}},[10]}, 1784: {{{A,t2,3},{'$M_EXPR','$F_EXPR',-1}},[14]}, 1785: {{{A,t2,3},{'$M_EXPR','$F_EXPR',1}},[15]}, 1786: {{{A,t3,1},{'$M_EXPR','$F_EXPR',3}},[19]}, 1787: {{{A,t3,1},{fun_mfa_vars,t,-1}},[18]}, 1788: {{{A,t4,2},{'$M_EXPR','$F_EXPR',3}},[22,23]}, 1789: {{{A,t5,2},{'$M_EXPR','$F_EXPR',0}},[27]}, 1790: {{{A,t5,2},{'$M_EXPR',t,-1}},[26]}]} = 1791: xref:q(s, "(Lin) E"), 1792: 1793: ok = check_state(s), 1794: xref:stop(s), 1795: 1796: ok = file:delete(File), 1797: ok = file:delete(Beam), 1798: ok. 1799: 1800: qlc(suite) -> []; 1801: qlc(doc) -> ["OTP-5195: A bug fix when using qlc:q/1,2."]; 1802: qlc(Conf) when is_list(Conf) -> 1803: Dir = ?copydir, 1804: File = fname(Dir, "qlc.erl"), 1805: MFile = fname(Dir, "qlc"), 1806: Beam = fname(Dir, "qlc.beam"), 1807: Test = <<"-module(qlc). 1808: 1809: -include_lib(\"stdlib/include/qlc.hrl\"). 1810: 1811: -export([t/0]). 1812: 1813: t() -> 1814: dets:open_file(t, []), 1815: dets:insert(t, [{1,a},{2,b},{3,c},{4,d}]), 1816: MS = ets:fun2ms(fun({X,Y}) when (X > 1) or (X < 5) -> {Y} 1817: end), 1818: QH1 = dets:table(t, [{traverse, {select, MS}}]), 1819: QH2 = qlc:q([{Y} || {X,Y} <- dets:table(t), 1820: (X > 1) or (X < 5)]), 1821: true = qlc:info(QH1) =:= qlc:info(QH2), 1822: dets:close(t), 1823: ok. 1824: ">>, 1825: 1826: ?line ok = file:write_file(File, Test), 1827: A = qlc, 1828: ?line {ok, A} = compile:file(File, [debug_info,{outdir,Dir}]), 1829: ?line {ok, _} = xref:start(s), 1830: ?line {ok, A} = xref:add_module(s, MFile, {warnings,false}), 1831: ?line {ok, _} = xref:q(s, "(Lin) E"), % is can be loaded 1832: 1833: ?line ok = check_state(s), 1834: ?line xref:stop(s), 1835: 1836: ?line ok = file:delete(File), 1837: ?line ok = file:delete(Beam), 1838: ok. 1839: 1840: 1841: 1842: analyze(suite) -> []; 1843: analyze(doc) -> ["Simple analyses"]; 1844: analyze(Conf) when is_list(Conf) -> 1845: S0 = new(), 1846: ?line {{error, _, {invalid_options,[not_an_option]}}, _} = 1847: xref_base:analyze(S0, undefined_function_calls, [not_an_option]), 1848: ?line {{error, _, {invalid_query,{q}}}, _} = xref_base:q(S0,{q}), 1849: ?line {{error, _, {unknown_analysis,foo}}, _} = xref_base:analyze(S0, foo), 1850: ?line {{error, _, {unknown_constant,"foo:bar/-1"}}, _} = 1851: xref_base:analyze(S0, {use,{foo,bar,-1}}), 1852: 1853: CopyDir = ?copydir, 1854: Dir = fname(CopyDir,"rel2"), 1855: X = fname(Dir, "x.erl"), 1856: Y = fname(Dir, "y.erl"), 1857: A1_1 = fname([Dir,"lib","app1-1.1"]), 1858: A2 = fname([Dir,"lib","app2-1.1"]), 1859: EB1_1 = fname(A1_1, "ebin"), 1860: EB2 = fname(A2, "ebin"), 1861: Xbeam = fname(EB2, "x.beam"), 1862: Ybeam = fname(EB1_1, "y.beam"), 1863: 1864: ?line {ok, x} = compile:file(X, [debug_info, {outdir,EB2}]), 1865: ?line {ok, y} = compile:file(Y, [debug_info, {outdir,EB1_1}]), 1866: 1867: ?line {ok, rel2, S1} = xref_base:add_release(S0, Dir, [{verbose,false}]), 1868: ?line S = set_up(S1), 1869: 1870: ?line {ok, _} = 1871: analyze(undefined_function_calls, [{{x,xx,0},{x,undef,0}}], S), 1872: ?line {ok, _} = analyze(undefined_functions, [{x,undef,0}], S), 1873: ?line {ok, _} = analyze(locals_not_used, [{x,l,0},{x,l1,0}], S), 1874: ?line {ok, _} = analyze(exports_not_used, [{x,xx,0},{y,t,0}], S), 1875: 1876: ?line {ok, _} = 1877: analyze(deprecated_function_calls, [{{y,t,0},{x,t,0}}], S), 1878: ?line {ok, _} = analyze({deprecated_function_calls,next_version}, [], S), 1879: ?line {ok, _} = 1880: analyze({deprecated_function_calls,next_major_release}, [], S), 1881: ?line {ok, _} = analyze({deprecated_function_calls,eventually}, 1882: [{{y,t,0},{x,t,0}}], S), 1883: ?line {ok, _} = analyze(deprecated_functions, [{x,t,0}], S), 1884: ?line {ok, _} = analyze({deprecated_functions,next_version}, [], S), 1885: ?line {ok, _} = 1886: analyze({deprecated_functions,next_major_release}, [], S), 1887: ?line {ok, _} = analyze({deprecated_functions,eventually}, [{x,t,0}], S), 1888: 1889: ?line {ok, _} = analyze({call, {x,xx,0}}, [{x,undef,0}], S), 1890: ?line {ok, _} = 1891: analyze({call, [{x,xx,0},{x,l,0}]}, [{x,l1,0},{x,undef,0}], S), 1892: ?line {ok, _} = analyze({use, {x,l,0}}, [{x,l1,0}], S), 1893: ?line {ok, _} = 1894: analyze({use, [{x,l,0},{x,l1,0}]}, [{x,l,0},{x,l1,0}], S), 1895: 1896: ?line {ok, _} = analyze({module_call, x}, [x], S), 1897: ?line {ok, _} = analyze({module_call, [x,y]}, [x], S), 1898: ?line {ok, _} = analyze({module_use, x}, [x,y], S), 1899: ?line {ok, _} = analyze({module_use, [x,y]}, [x,y], S), 1900: 1901: ?line {ok, _} = analyze({application_call, app1}, [app2], S), 1902: ?line {ok, _} = analyze({application_call, [app1,app2]}, [app2], S), 1903: ?line {ok, _} = analyze({application_use, app2}, [app1,app2], S), 1904: ?line {ok, _} = analyze({application_use, [app1,app2]}, [app1,app2], S), 1905: 1906: ?line ok = xref_base:delete(S), 1907: ?line ok = file:delete(Xbeam), 1908: ?line ok = file:delete(Ybeam), 1909: ok. 1910: 1911: basic(suite) -> []; 1912: basic(doc) -> ["Use of operators"]; 1913: basic(Conf) when is_list(Conf) -> 1914: ?line S0 = new(), 1915: 1916: F1 = {m1,f1,1}, 1917: F6 = {m1,f2,6}, % X 1918: F2 = {m2,f1,2}, 1919: F3 = {m2,f2,3}, % X 1920: F7 = {m2,f3,7}, % X 1921: F4 = {m3,f1,4}, % X 1922: F5 = {m3,f2,5}, 1923: 1924: UF1 = {m1,f12,17}, 1925: UF2 = {m17,f17,177}, 1926: 1927: E1 = {F1,F3}, % X 1928: E2 = {F6,F7}, % X 1929: E3 = {F2,F6}, % X 1930: E4 = {F1,F4}, % X 1931: E5 = {F4,F5}, 1932: E6 = {F7,F4}, % X 1933: E7 = {F1,F6}, 1934: 1935: UE1 = {F2,UF2}, % X 1936: UE2 = {F5,UF1}, % X 1937: 1938: D1 = {F1,12}, 1939: D6 = {F6,3}, 1940: DefAt_m1 = [D1,D6], 1941: X_m1 = [F6], 1942: % L_m1 = [F1], 1943: XC_m1 = [E1,E2,E4], 1944: LC_m1 = [E7], 1945: LCallAt_m1 = [{E7,12}], 1946: XCallAt_m1 = [{E1,13},{E2,17},{E4,7}], 1947: Info1 = #xref_mod{name = m1, app_name = [a1]}, 1948: ?line S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, 1949: XC_m1, LC_m1), 1950: 1951: D2 = {F2,7}, 1952: D3 = {F3,9}, 1953: D7 = {F7,19}, 1954: DefAt_m2 = [D2,D3,D7], 1955: X_m2 = [F3,F7], 1956: % L_m2 = [F2], 1957: XC_m2 = [E3,E6,UE1], 1958: LC_m2 = [], 1959: LCallAt_m2 = [], 1960: XCallAt_m2 = [{E3,96},{E6,12},{UE1,77}], 1961: Info2 = #xref_mod{name = m2, app_name = [a2]}, 1962: ?line S2 = add_module(S1, Info2, DefAt_m2, X_m2, LCallAt_m2, XCallAt_m2, 1963: XC_m2, LC_m2), 1964: 1965: D4 = {F4,6}, 1966: D5 = {F5,97}, 1967: DefAt_m3 = [D4,D5], 1968: X_m3 = [F4], 1969: % L_m3 = [F5], 1970: XC_m3 = [UE2], 1971: LC_m3 = [E5], 1972: LCallAt_m3 = [{E5,19}], 1973: XCallAt_m3 = [{UE2,22}], 1974: Info3 = #xref_mod{name = m3, app_name = [a3]}, 1975: ?line S3 = add_module(S2, Info3, DefAt_m3, X_m3, LCallAt_m3, XCallAt_m3, 1976: XC_m3, LC_m3), 1977: 1978: Info4 = #xref_mod{name = m4, app_name = [a2]}, 1979: ?line S4 = add_module(S3, Info4, [], [], [], [], [], []), 1980: 1981: AppInfo1 = #xref_app{name = a1, rel_name = [r1]}, 1982: ?line S9 = add_application(S4, AppInfo1), 1983: AppInfo2 = #xref_app{name = a2, rel_name = [r1]}, 1984: ?line S10 = add_application(S9, AppInfo2), 1985: AppInfo3 = #xref_app{name = a3, rel_name = [r2]}, 1986: ?line S11 = add_application(S10, AppInfo3), 1987: 1988: RelInfo1 = #xref_rel{name = r1}, 1989: ?line S12 = add_release(S11, RelInfo1), 1990: RelInfo2 = #xref_rel{name = r2}, 1991: ?line S13 = add_release(S12, RelInfo2), 1992: 1993: ?line S = set_up(S13), 1994: 1995: ?line {ok, _} = eval("[m1,m2] + m:f/1", unknown_constant, S), 1996: ?line {ok, _} = eval("[m1, m2, m:f/1]", type_mismatch, S), 1997: 1998: ?line {ok, _} = eval("[m1, m1->m2]", type_mismatch, S), 1999: ?line {ok, _} = eval("components:f/1", unknown_constant, S), 2000: ?line {ok, _} = eval("'of':f/1", unknown_constant, S), 2001: ?line {ok, _} = eval("of:f/1", parse_error, S), 2002: ?line {ok, _} = eval("components", unknown_constant, S), 2003: ?line {ok, _} = eval("[components, of, closure]", parse_error, S), 2004: ?line {ok, _} = eval("[components, 'of', closure]", unknown_constant, S), 2005: 2006: ?line {ok, _} = eval("[a1->a2,m1->m2]", type_mismatch, S), 2007: ?line {ok, _} = eval("a1->a2,m1->m2", parse_error, S), 2008: 2009: ?line {ok, _} = eval("m1->a1", type_mismatch, S), 2010: ?line {ok, _} = eval("[{m1,f1,1}] : App", parse_error, S), 2011: ?line {ok, _} = eval("[{m1,f1,1}] : Fun", [F1], S), 2012: ?line {ok, _} = eval("range X", type_error, S), 2013: ?line {ok, _} = eval("domain X", type_error, S), 2014: ?line {ok, _} = eval("range M", type_error, S), 2015: ?line {ok, _} = eval("domain M", type_error, S), 2016: 2017: % Misc. 2018: ?line {ok, _} = eval("not_a_prefix_operator m1", parse_error, S), 2019: ?line {ok, _} = eval(f("(Mod) ~p", [[F1,F6,F5]]), [m1,m3], S), 2020: ?line {ok, _} = eval("(Lin) M - (Lin) m1", 2021: [{F2,7},{F3,9},{F7,19},{F4,6},{F5,97},{UF2,0}], S), 2022: ?line {ok, _} = eval(f("(Lin) M * (Lin) ~p", [[F1,F6]]), 2023: [{F1,12},{F6,3}], S), 2024: 2025: ?line {ok, _} = eval(f("X * ~p", [[F1, F2, F3, F4, F5]]), [F3, F4], S), 2026: ?line {ok, _} = eval("X", [F6,F3,F7,F4], S), 2027: ?line {ok, _} = eval("X * AM", [F6,F3,F7,F4], S), 2028: ?line {ok, _} = eval("X * a2", [F3,F7], S), 2029: 2030: ?line {ok, _} = eval("L * r1", [F1,F2], S), 2031: ?line {ok, _} = eval("U", [UF1, UF2], S), 2032: ?line {ok, _} = eval("U * AM", [UF1], S), 2033: ?line {ok, _} = eval("U * UM", [UF2], S), 2034: ?line {ok, _} = eval("XU * [m1, m2]", [F6,F3,F7,UF1], S), 2035: ?line {ok, _} = eval("LU * [m3, m4]", [F5], S), 2036: ?line {ok, _} = eval("UU", [F1,F2], S), 2037: 2038: ?line {ok, _} = eval("XC | m1", [E1,E2,E4], S), 2039: ?line {ok, _} = eval(f("XC | ~p", [F1]), [E1,E4], S), 2040: ?line {ok, _} = eval(f("(XXL) (Lin) (XC | ~p)", [F1]), 2041: [{{D1,D3},[13]},{{D1,D4},[7]}],S), 2042: ?line {ok, _} = eval(f("XC | (~p + ~p)", [F1, F2]), [E1,E4,E3,UE1], S), 2043: ?line {ok, _} = eval(f("(XXL) (Lin) (XC | ~p)", [F1]), 2044: [{{D1,D3},[13]},{{D1,D4},[7]}], S), 2045: ?line {ok, _} = eval("LC | m3", [E5], S), 2046: ?line {ok, _} = eval(f("LC | ~p", [F1]), [E7], S), 2047: ?line {ok, _} = eval(f("LC | (~p + ~p)", [F1, F4]), [E7, E5], S), 2048: ?line {ok, _} = eval("E | m1", [E1,E2,E4,E7], S), 2049: ?line {ok, _} = eval(f("E | ~p", [F1]), [E1,E7,E4], S), 2050: ?line {ok, _} = eval(f("E | (~p + ~p)", [F1, F2]), [E1,E7,E4,E3,UE1], S), 2051: 2052: ?line {ok, _} = eval("XC || m1", [E3,UE2], S), 2053: ?line {ok, _} = eval(f("XC || ~p", [F6]), [E3], S), 2054: ?line {ok, _} = eval(f("XC || (~p + ~p)", [F4, UF2]), [UE1,E4,E6], S), 2055: ?line {ok, _} = eval("LC || m3", [E5], S), 2056: ?line {ok, _} = eval(f("LC || ~p", [F1]), [], S), 2057: ?line {ok, _} = eval(f("LC || ~p", [F6]), [E7], S), 2058: ?line {ok, _} = eval(f("LC || (~p + ~p)", [F5, F6]), [E7,E5], S), 2059: ?line {ok, _} = eval("E || m1", [E3,UE2,E7], S), 2060: ?line {ok, _} = eval(f("E || ~p", [F6]), [E3,E7], S), 2061: ?line {ok, _} = eval(f("E || (~p + ~p)", [F3,F4]), [E1,E4,E6], S), 2062: 2063: ?line {ok, _} = eval(f("~p + ~p", [F1,F2]), [F1,F2], S), 2064: ?line {ok, _} = eval(f("~p * ~p", [m1,[F1,F6,F2]]), [F1,F6], S), 2065: ?line {ok, _} = eval(f("~p * ~p", [F1,F2]), [], S), 2066: 2067: %% range, domain 2068: ?line {ok, _} = eval("range (E || m1)", [F6,UF1], S), 2069: ?line {ok, _} = eval("domain (E || m1)", [F1,F2,F5], S), 2070: ?line {ok, _} = eval(f("E | domain ~p", [[E1, {F2,F4}]]), 2071: [E1,E7,E4,E3,UE1], S), 2072: 2073: %% components, condensation, use, call 2074: ?line {ok, _} = eval("(Lin) components E", type_error, S), 2075: ?line {ok, _} = eval("components (Lin) E", type_error, S), 2076: ?line {ok, _} = eval("components V", type_error, S), 2077: ?line {ok, _} = eval("components E + components E", type_error, S), 2078: 2079: ?line {ok, _} = eval(f("range (closure E | ~p)", [[F1,F2]]), 2080: [F6,F3,F7,F4,F5,UF1,UF2], S), 2081: ?line {ok, _} = 2082: eval(f("domain (closure E || ~p)", [[UF2,F7]]), [F1,F2,F6], S), 2083: ?line {ok, _} = eval("components E", [], S), 2084: ?line {ok, _} = eval("components (Mod) E", [[m1,m2,m3]], S), 2085: ?line {ok, _} = eval("components closure (Mod) E", [[m1,m2,m3]], S), 2086: ?line {ok, _} = eval("condensation (Mod) E", 2087: [{[m1,m2,m3],[m17]}], S), 2088: ?line {ok, _} = eval("condensation closure (Mod) E", 2089: [{[m1,m2,m3],[m17]}], S), 2090: ?line {ok, _} = eval("condensation closure closure closure (Mod) E", 2091: [{[m1,m2,m3],[m17]}], S), 2092: ?line {ok, _} = eval("weak condensation (Mod) E", 2093: [{[m1,m2,m3],[m1,m2,m3]},{[m1,m2,m3],[m17]},{[m17],[m17]}], S), 2094: ?line {ok, _} = eval("strict condensation (Mod) E", 2095: [{[m1,m2,m3],[m17]}], S), 2096: ?line {ok, _} = eval("range condensation (Mod) E", 2097: [[m17]], S), 2098: ?line {ok, _} = eval("domain condensation (Mod) E", 2099: [[m1,m2,m3]], S), 2100: 2101: %% |, ||, ||| 2102: ?line {ok, _} = eval("(Lin) E || V", type_error, S), 2103: ?line {ok, _} = eval("E ||| (Lin) V", type_error, S), 2104: ?line {ok, _} = eval("E ||| m1", [E7], S), 2105: ?line {ok, _} = eval("closure E ||| m1", [E7,{F1,UF1},{F6,UF1}], S), 2106: ?line {ok, _} = eval("closure E ||| [m1,m2]", 2107: [{F1,UF1},{F2,F7},{F1,F7},{F6,UF1},{F2,UF1},{F7,UF1},E7,E1,E2,E3], S), 2108: ?line {ok, _} = eval("AE | a1", [{a1,a1},{a1,a2},{a1,a3}], S), 2109: 2110: %% path ('of') 2111: ?line {ok, _} = eval("(Lin) {m1,m2} of E", type_error, S), 2112: ?line {ok, _} = eval("{m1,m2} of (Lin) E", type_error, S), 2113: ?line [m1,m2] = eval("{m1,m2} of {m1,m2}", S), 2114: ?line {ok, _} = eval("{m1,m2} of m1", type_error, S), 2115: ?line {ok, _} = eval("{a3,m1} of ME", type_mismatch, S), 2116: ?line [m1,m1] = eval("{m1} of ME", S), 2117: ?line [m1,m1] = eval("{m1} of closure closure ME", S), 2118: ?line false = eval("{m17} of ME", S), 2119: ?line [m2,m1,m2] = eval("{m2} : Mod of ME", S), 2120: ?line [m1,m2,m17] = eval("{m1, m17} of ME", S), 2121: ?line [m1,m2,m17] = eval("m1 -> m17 of ME", S), 2122: ?line {ok, _} = eval("[m1->m17,m17->m1] of ME", type_error, S), 2123: ?line case eval(f("~p of E", [{F1,F7,UF1}]), S) of 2124: [F1,F6,F7,F4,F5,UF1] -> ok 2125: end, 2126: ?line [a2,a1,a2] = eval("{a2} of AE", S), 2127: 2128: %% weak/strict 2129: ?line {ok, _} = eval("weak {m1,m2}", [{m1,m1},{m1,m2},{m2,m2}], S), 2130: ?line {ok, _} = eval("strict [{m1,m1},{m1,m2},{m2,m2}]", [{m1,m2}], S), 2131: ?line {ok, _} = eval("range weak [{m1,m2}] : Mod", [m1,m2], S), 2132: ?line {ok, _} = eval("domain strict [{m1,m1},{m1,m2},{m2,m2}]", [m1], S), 2133: 2134: %% #, number of 2135: ?line {ok, _} = eval("# [{r1,r2}] : Rel", 1, S), 2136: ?line {ok, _} = eval("# [{a3,a1}] : App", 1, S), 2137: ?line {ok, _} = eval("# AE", 7, S), 2138: ?line {ok, _} = eval("# ME", 8, S), 2139: ?line {ok, _} = eval("# AE + # ME", 15, S), 2140: ?line {ok, _} = eval("# AE * # ME", 56, S), 2141: ?line {ok, _} = eval("# AE - # ME", -1, S), 2142: ?line {ok, _} = eval("# E", 9, S), 2143: ?line {ok, _} = eval("# V", 9, S), 2144: ?line {ok, _} = eval("# (Lin) E", 9, S), 2145: ?line {ok, _} = eval("# (ELin) E", 7, S), 2146: ?line {ok, _} = eval("# closure E", type_error, S), 2147: ?line {ok, _} = eval("# weak {m1,m2}", 3, S), 2148: ?line {ok, _} = eval("#strict condensation (Mod) E", 1, S), 2149: ?line {ok, _} = eval("#components closure (Mod) E", 1, S), 2150: ?line {ok, _} = eval("# range strict condensation (Mod) E", 1, S), 2151: ok. 2152: 2153: md(suite) -> []; 2154: md(doc) -> ["The xref:m() and xref:d() functions"]; 2155: md(Conf) when is_list(Conf) -> 2156: CopyDir = ?copydir, 2157: Dir = fname(CopyDir,"md"), 2158: X = fname(Dir, "x__x.erl"), 2159: Y = fname(Dir, "y__y.erl"), 2160: Xbeam = fname(Dir, "x__x.beam"), 2161: Ybeam = fname(Dir, "y__y.beam"), 2162: 2163: ?line {error, _, {invalid_filename,{foo,bar}}} = xref:m({foo,bar}), 2164: ?line {error, _, {invalid_filename,{foo,bar}}} = xref:d({foo,bar}), 2165: 2166: ?line {ok, x__x} = compile:file(X, [debug_info, {outdir,Dir}]), 2167: ?line {ok, y__y} = compile:file(Y, [debug_info, {outdir,Dir}]), 2168: 2169: ?line {error, _, {no_such_module, foo_bar}} = xref:m(foo_bar), 2170: ?line OldPath = code:get_path(), 2171: ?line true = code:set_path([Dir | OldPath]), 2172: ?line MInfo = xref:m(x__x), 2173: ?line [{{x__x,t,1},{y__y,t,2}}] = info_tag(MInfo, undefined), 2174: ?line [] = info_tag(MInfo, unused), 2175: ?line [] = info_tag(MInfo, deprecated), 2176: ?line DInfo = xref:d(Dir), 2177: ?line [{{x__x,t,1},{y__y,t,2}}] = info_tag(DInfo, undefined), 2178: ?line [{y__y,l,0},{y__y,l1,0}] = info_tag(DInfo, unused), 2179: ?line [] = info_tag(MInfo, deprecated), 2180: 2181: %% Switch from 'functions' mode to 'modules' mode. 2182: ?line {ok, x__x} = compile:file(X, [no_debug_info, {outdir,Dir}]), 2183: ?line {ok, y__y} = compile:file(Y, [no_debug_info, {outdir,Dir}]), 2184: ?line MInfoMod = xref:m(x__x), 2185: ?line [{y__y,t,2}] = info_tag(MInfoMod, undefined), 2186: ?line [] = info_tag(MInfo, deprecated), 2187: ?line DInfoMod = xref:d(Dir), 2188: ?line [{y__y,t,2}] = info_tag(DInfoMod, undefined), 2189: ?line [] = info_tag(MInfo, deprecated), 2190: 2191: ?line true = code:set_path(OldPath), 2192: ?line ok = file:delete(Xbeam), 2193: ?line ok = file:delete(Ybeam), 2194: ok. 2195: 2196: q(suite) -> []; 2197: q(doc) -> ["User queries"]; 2198: q(Conf) when is_list(Conf) -> 2199: ?line S0 = new(), 2200: ?line {ok, _} = eval("'foo", parse_error, S0), 2201: ?line {ok, _} = eval("TT = E, TT = V", variable_reassigned, S0), 2202: ?line {ok, _} = eval("TT = E, TTT", unknown_variable, S0), 2203: ?line {ok, S} = eval("TT := E", [], S0), 2204: ?line {ok, S1} = eval("TT * TT * TT", [], S), 2205: ?line {ok, _S2} = xref_base:forget(S1, 'TT'), 2206: ok. 2207: 2208: variables(suite) -> []; 2209: variables(doc) -> ["Setting and getting values of query variables"]; 2210: variables(Conf) when is_list(Conf) -> 2211: ?line Sa = new(), 2212: ?line {{error, _, {invalid_options,[not_an_option]}}, _} = 2213: xref_base:variables(Sa, [not_an_option]), 2214: ?line {error, _, {not_user_variable,foo}} = xref_base:forget(Sa, foo), 2215: ?line Sa1 = set_up(Sa), 2216: ?line {error, _, {not_user_variable,foo}} = xref_base:forget(Sa1, foo), 2217: ?line ok = xref_base:delete(Sa1), 2218: 2219: ?line S0 = new(), 2220: 2221: F1 = {m1,f1,1}, 2222: F2 = {m2,f1,2}, 2223: Lib = {lib1,f1,1}, % undefined 2224: 2225: E1 = {F1,F2}, 2226: E2 = {F2,F1}, 2227: E3 = {F1,Lib}, 2228: 2229: D1 = {F1,12}, 2230: DefAt_m1 = [D1], 2231: X_m1 = [F1], 2232: % L_m1 = [], 2233: XC_m1 = [E1,E3], 2234: LC_m1 = [], 2235: LCallAt_m1 = [], 2236: XCallAt_m1 = [{E1,13},{E3,17}], 2237: Info1 = #xref_mod{name = m1, app_name = [a1]}, 2238: ?line S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, 2239: XC_m1, LC_m1), 2240: 2241: D2 = {F2,7}, 2242: DefAt_m2 = [D2], 2243: X_m2 = [F2], 2244: % L_m2 = [], 2245: XC_m2 = [E2], 2246: LC_m2 = [], 2247: LCallAt_m2 = [], 2248: XCallAt_m2 = [{E2,96}], 2249: Info2 = #xref_mod{name = m2, app_name = [a2]}, 2250: ?line S2 = add_module(S1, Info2, DefAt_m2, X_m2, LCallAt_m2, XCallAt_m2, 2251: XC_m2, LC_m2), 2252: 2253: ?line S = set_up(S2), 2254: 2255: ?line eval("T1=E, T2=E*T1, T3 = T2*T2, T4=range T3, T5=T3|T4, T5", 2256: [E1,E2,E3], S), 2257: ?line eval("((E*E)*(E*E)) | (range ((E*E)*(E*E)))", 2258: [E1,E2,E3], S), 2259: ?line eval("T1=V*V,T2=T1*V,T3=V*V*V,T3", 2260: [F1,F2,Lib], S), 2261: ?line eval("T1=V*V, T2=V*V, T1*T2", 2262: [F1,F2,Lib], S), 2263: 2264: ?line {ok, S100} = eval("T0 := E", [E1, E2, E3], S), 2265: ?line {ok, S101} = eval("T1 := E | m1", [E1, E3], S100), 2266: ?line {ok, S102} = eval("T2 := E | m2", [E2], S101), 2267: ?line {{ok, [{user, ['T0', 'T1', 'T2']}]}, _} = xref_base:variables(S102), 2268: ?line {ok, S103} = xref_base:forget(S102, 'T0'), 2269: ?line {{ok, [{user, ['T1', 'T2']}]}, S104} = 2270: xref_base:variables(S103, [user]), 2271: ?line {ok, S105} = xref_base:forget(S104), 2272: ?line {{ok, [{user, []}]}, S106} = xref_base:variables(S105), 2273: ?line {{ok, [{predefined,_}]}, S107_0} = 2274: xref_base:variables(S106, [predefined]), 2275: 2276: ?line {ok, S107_1} = 2277: eval("TT := E, TT2 := V, TT1 := TT * TT", [E1,E2,E3], S107_0), 2278: ?line {{ok, [{user, ['TT', 'TT1', 'TT2']}]}, _} = 2279: xref_base:variables(S107_1), 2280: ?line {ok, S107} = xref_base:forget(S107_1), 2281: 2282: CopyDir = ?copydir, 2283: ?line Dir = fname(CopyDir,"lib_test"), 2284: Beam = fname(Dir, "lib1.beam"), 2285: 2286: ?line copy_file(fname(Dir, "lib1.erl"), Beam), 2287: ?line {ok, S108} = 2288: xref_base:set_library_path(S107, [Dir], [{verbose,false}]), 2289: ?line {{error, _, _}, _} = xref_base:variables(S108, [{verbose,false}]), 2290: ?line {ok, S109} = xref_base:set_library_path(S108, [], [{verbose,false}]), 2291: 2292: ?line Tabs = length(ets:all()), 2293: 2294: ?line {ok, S110} = eval("Eplus := closure E, TT := Eplus", 2295: 'closure()', S109), 2296: ?line {{ok, [{user, ['Eplus','TT']}]}, S111} = xref_base:variables(S110), 2297: ?line {ok, S112} = xref_base:forget(S111, ['TT','Eplus']), 2298: ?line true = Tabs =:= length(ets:all()), 2299: 2300: ?line {ok, NS0} = eval("Eplus := closure E", 'closure()', S112), 2301: ?line {{ok, [{user, ['Eplus']}]}, NS} = xref_base:variables(NS0), 2302: ?line ok = xref_base:delete(NS), 2303: ?line true = Tabs =:= length(ets:all()), 2304: 2305: ?line ok = file:delete(Beam), 2306: ok. 2307: 2308: unused_locals(suite) -> []; 2309: unused_locals(doc) -> ["OTP-5071. Too many unused functions."]; 2310: unused_locals(Conf) when is_list(Conf) -> 2311: Dir = ?copydir, 2312: 2313: File1 = fname(Dir, "a.erl"), 2314: MFile1 = fname(Dir, "a"), 2315: Beam1 = fname(Dir, "a.beam"), 2316: Test1 = <<"-module(a). 2317: -export([f/1, g/2]). 2318: 2319: f(X) -> 2320: Y = b:f(X), 2321: Z = b:g(Y), 2322: start(b, h, [Z]). 2323: 2324: g(X, Y) -> 2325: ok. 2326: 2327: start(M, F, A) -> 2328: spawn(M, F, A). 2329: ">>, 2330: ?line ok = file:write_file(File1, Test1), 2331: ?line {ok, a} = compile:file(File1, [debug_info,{outdir,Dir}]), 2332: 2333: File2 = fname(Dir, "b.erl"), 2334: MFile2 = fname(Dir, "b"), 2335: Beam2 = fname(Dir, "b.beam"), 2336: Test2 = <<"-module(b). 2337: -export([f/1, g/2]). 2338: 2339: f(X) -> 2340: io:write(\"~w\", [X]), 2341: a:start(timer, sleep, [1000]). 2342: 2343: g(X, Y) -> 2344: apply(a, g, [X, Y]). 2345: ">>, 2346: 2347: ?line ok = file:write_file(File2, Test2), 2348: ?line {ok, b} = compile:file(File2, [debug_info,{outdir,Dir}]), 2349: 2350: ?line {ok, _} = xref:start(s), 2351: ?line {ok, a} = xref:add_module(s, MFile1), 2352: ?line {ok, b} = xref:add_module(s, MFile2), 2353: ?line {ok, []} = xref:analyse(s, locals_not_used), 2354: ?line ok = check_state(s), 2355: ?line xref:stop(s), 2356: 2357: ?line ok = file:delete(File1), 2358: ?line ok = file:delete(Beam1), 2359: ?line ok = file:delete(File2), 2360: ?line ok = file:delete(Beam2), 2361: ok. 2362: 2363: 2364: format_error(suite) -> []; 2365: format_error(doc) -> ["Format error messages"]; 2366: format_error(Conf) when is_list(Conf) -> 2367: ?line {ok, _Pid} = start(s), 2368: ?line ok = xref:set_default(s, [{verbose,false}, {warnings, false}]), 2369: 2370: %% Parse error messages. 2371: ?line "Invalid regular expression \"add(\"" ++ _ = 2372: fstring(xref:q(s,'"add("')), 2373: ?line 'Invalid operator foo\n' = 2374: fatom(xref:q(s,'foo E')), 2375: ?line 'Invalid wildcard variable \'_Var\' (only \'_\' is allowed)\n' 2376: = fatom(xref:q(s,"module:function/_Var")), 2377: ?line 'Missing type of regular expression ".*"\n' 2378: = fatom(xref:q(s,'".*"')), 2379: ?line 'Type does not match structure of constant: \'M\' : Fun\n' 2380: = fatom(xref:q(s,"'M' : Fun")), 2381: ?line 'Type does not match structure of constant: ".*" : Fun\n' 2382: = fatom(xref:q(s,'".*" : Fun')), 2383: ?line 'Type does not match structure of constant: [m:f/1, m1:f2/3] : App\n' 2384: = fatom(xref:q(s,"[m:f/1,m1:f2/3] : App")), 2385: ?line 'Parse error on line 1: syntax error before: \'-\'\n' = 2386: fatom(xref:q(s,"E + -")), 2387: ?line "Parse error on line 1: unterminated atom starting with 'foo'\n" 2388: = flatten(xref:format_error(xref:q(s,"'foo"))), 2389: ?line 'Parse error at end of string: syntax error before: \n' = 2390: fatom(xref:q(s,"E +")), 2391: ?line 'Parse error on line 1: syntax error before: \'Lin\'\n' = 2392: fatom(xref:q(s,"Lin")), 2393: 2394: %% Other messages 2395: ?line 'Variable \'QQ\' used before set\n' = 2396: fatom(xref:q(s,"QQ")), 2397: ?line 'Unknown constant a\n' = 2398: fatom(xref:q(s,"{a} of E")), 2399: 2400: %% Testing xref_parser:t2s/1. 2401: ?line 'Variable assigned more than once: E := E + E\n' = 2402: fatom(xref:q(s,"E:=E + E")), 2403: ?line 'Variable assigned more than once: E = E + E\n' = 2404: fatom(xref:q(s,"E=E + E")), 2405: ?line "Operator applied to argument(s) of different or invalid type(s): " 2406: "E + V * V\n" = 2407: flatten(xref:format_error(xref:q(s,"E + (V * V)"))), 2408: ?line {error,xref_compiler,{type_error,"(V + V) * E"}} = 2409: xref:q(s,"(V + V) * E"), 2410: ?line "Type does not match structure of constant: [m:f/3 -> g:h/17] : " 2411: "App\n" = 2412: flatten(xref:format_error(xref:q(s,"[{{m,f,3},{g,h,17}}] : App"))), 2413: ?line 'Type does not match structure of constant: [m -> f, g -> h] : Fun\n' 2414: = fatom(xref:q(s,"[{m,f},g->h] : Fun")), 2415: ?line 'Type does not match structure of constant: {m, n, o} : Fun\n' = 2416: fatom(xref:q(s,"{m,n,o} : Fun")), 2417: ?line {error,xref_compiler,{type_error,"range (Lin) V"}} = 2418: xref:q(s,"range ((Lin) V)"), 2419: ?line {error,xref_compiler,{type_error,"condensation range E"}} = 2420: xref:q(s,"condensation (range E)"), 2421: ?line {error,xref_compiler,{type_error,"condensation (# E + # V)"}} = 2422: xref:q(s,"condensation (# E + # V)"), 2423: ?line {error,xref_compiler,{type_error,"range (# E + # E)"}} = 2424: xref:q(s,"range (#E + #E)"), 2425: ?line {error,xref_compiler,{type_error,"range (# E)"}} = 2426: xref:q(s,"range #E"), % Hm... 2427: ?line {error,xref_compiler,{type_error,"E + # E"}} = 2428: xref:q(s,"E + #E + #E"), % Hm... 2429: ?line {error,xref_compiler,{type_error,"V * E || V | V"}} = 2430: xref:q(s,"V * (E || V) | V"), 2431: ?line {error,xref_compiler,{type_error,"E || (E | V)"}} = 2432: xref:q(s,"V * E || (E | V)"), 2433: ?line {error,xref_compiler,{type_error,"E * \"m\" : Mod"}} = 2434: xref:q(s,'E * "m" : Mod'), 2435: ?line {error,xref_compiler,{type_error,"E * (\"m\":f/_ + m:\"f\"/3)"}} = 2436: xref:q(s,'E * ("m":f/_ + m:"f"/3)'), 2437: 2438: ?line xref:stop(s), 2439: ok. 2440: 2441: otp_7423(suite) -> []; 2442: otp_7423(doc) -> ["OTP-7423. Xref scanner bug."]; 2443: otp_7423(Conf) when is_list(Conf) -> 2444: ?line {ok, _Pid} = start(s), 2445: S = "E | [compiler] : App || [{erlang, 2446: size, 2447: 1}] : Fun", 2448: ?line {error,xref_compiler,{unknown_constant,"compiler"}} = xref:q(s,S), 2449: ?line xref:stop(s), 2450: ok. 2451: 2452: otp_7831(suite) -> []; 2453: otp_7831(doc) -> ["OTP-7831. Allow anonymous Xref processes."]; 2454: otp_7831(Conf) when is_list(Conf) -> 2455: ?line {ok, Pid1} = xref:start([]), 2456: ?line xref:stop(Pid1), 2457: ?line {ok, Pid2} = xref:start([{xref_mode, modules}]), 2458: ?line xref:stop(Pid2), 2459: ok. 2460: 2461: otp_10192(suite) -> []; 2462: otp_10192(doc) -> 2463: ["OTP-10192. Allow filenames with character codes greater than 126."]; 2464: otp_10192(Conf) when is_list(Conf) -> 2465: PrivDir = ?privdir, 2466: {ok, _Pid} = xref:start(s), 2467: Dir = filename:join(PrivDir, "รค"), 2468: ok = file:make_dir(Dir), 2469: {ok, []} = xref:add_directory(s, Dir), 2470: xref:stop(s), 2471: ok. 2472: 2473: %%% 2474: %%% Utilities 2475: %%% 2476: 2477: copy_file(Src, Dest) -> 2478: file:copy(Src, Dest). 2479: 2480: fname(N) -> 2481: filename:join(N). 2482: 2483: fname(Dir, Basename) -> 2484: filename:join(Dir, Basename). 2485: 2486: new() -> 2487: ?line {ok, S} = xref_base:new(), 2488: S. 2489: 2490: set_up(S) -> 2491: ?line {ok, S1} = xref_base:set_up(S, [{verbose, false}]), 2492: S1. 2493: 2494: eval(Query, E, S) -> 2495: ?format("------------------------------~n", []), 2496: ?format("Evaluating ~p~n", [Query]), 2497: ?line {Answer, NewState} = xref_base:q(S, Query, [{verbose, false}]), 2498: {Reply, Expected} = 2499: case Answer of 2500: {ok, R} when is_list(E) -> 2501: {unsetify(R), sort(E)}; 2502: {ok, R} -> 2503: {unsetify(R), E}; 2504: {error, _Module, Reason} -> 2505: {element(1, Reason), E} 2506: end, 2507: if 2508: Reply =:= Expected -> 2509: ?format("As expected, got ~n~p~n", [Expected]), 2510: {ok, NewState}; 2511: true -> 2512: ?format("Expected ~n~p~nbut got ~n~p~n", [Expected, Reply]), 2513: not_ok 2514: end. 2515: 2516: analyze(Query, E, S) -> 2517: ?format("------------------------------~n", []), 2518: ?format("Evaluating ~p~n", [Query]), 2519: ?line {{ok, L}, NewState} = 2520: xref_base:analyze(S, Query, [{verbose, false}]), 2521: case {unsetify(L), sort(E)} of 2522: {X,X} -> 2523: ?format("As was expected, got ~n~p~n", [X]), 2524: {ok, NewState}; 2525: {_R,_X} -> 2526: ?format("Expected ~n~p~nbut got ~n~p~n", [_X, _R]), 2527: not_ok 2528: end. 2529: 2530: unsetify(S) -> 2531: case is_sofs_set(S) of 2532: true -> to_external(S); 2533: false -> S 2534: end. 2535: 2536: %% Note: assumes S has been set up; the new state is not returned 2537: eval(Query, S) -> 2538: ?line {{ok, Answer}, _NewState} = 2539: xref_base:q(S, Query, [{verbose, false}]), 2540: unsetify(Answer). 2541: 2542: add_module(S, XMod, DefAt, X, LCallAt, XCallAt, XC, LC) -> 2543: Attr = {[], [], []}, 2544: Depr0 = {[], [], [], []}, 2545: DBad = [], 2546: Depr = {Depr0,DBad}, 2547: Data = {DefAt, LCallAt, XCallAt, LC, XC, X, Attr, Depr}, 2548: Unres = [], 2549: ?line {ok, _Module, _Bad, State} = 2550: xref_base:do_add_module(S, XMod, Unres, Data), 2551: State. 2552: 2553: add_application(S, XApp) -> 2554: ?line xref_base:do_add_application(S, XApp). 2555: 2556: add_release(S, XRel) -> 2557: ?line xref_base:do_add_release(S, XRel). 2558: 2559: remove_module(S, M) -> 2560: ?line xref_base:do_remove_module(S, M). 2561: 2562: info_tag(Info, Tag) -> 2563: {value, {_Tag, Value}} = lists:keysearch(Tag, 1, Info), 2564: Value. 2565: 2566: make_ufile(FileName) -> 2567: ?line ok = file:write_file(FileName, term_to_binary(foo)), 2568: ?line hide_file(FileName). 2569: 2570: make_udir(Dir) -> 2571: ?line ok = file:make_dir(Dir), 2572: ?line hide_file(Dir). 2573: 2574: hide_file(FileName) -> 2575: ?line {ok, FileInfo} = file:read_file_info(FileName), 2576: ?line NewFileInfo = FileInfo#file_info{mode = 0}, 2577: ?line ok = file:write_file_info(FileName, NewFileInfo). 2578: 2579: %% Note that S has to be set up before calling this checking function. 2580: check_state(S) -> 2581: ?line Info = xref:info(S), 2582: 2583: ?line modules_mode_check(S, Info), 2584: case info(Info, mode) of 2585: modules -> 2586: ok; 2587: functions -> 2588: functions_mode_check(S, Info) 2589: end. 2590: 2591: %% The manual mentions some facts that should always hold. 2592: %% Here they are again. 2593: functions_mode_check(S, Info) -> 2594: %% F = L + X, 2595: ?line {ok, F} = xref:q(S, "F"), 2596: ?line {ok, F} = xref:q(S, "L + X"), 2597: 2598: %% V = X + L + B + U, 2599: ?line {ok, V} = xref:q(S, "V"), 2600: ?line {ok, V} = xref:q(S, "X + L + B + U"), 2601: 2602: %% X, L, B and U are disjoint. 2603: ?line {ok, []} = 2604: xref:q(S, "X * L + X * B + X * U + L * B + L * U + B * U"), 2605: 2606: %% V = UU + XU + LU, 2607: ?line {ok, V} = xref:q(S, "UU + XU + LU"), 2608: 2609: %% E = LC + XC 2610: ?line {ok, E} = xref:q(S, "E"), 2611: ?line {ok, E} = xref:q(S, "LC + XC"), 2612: 2613: %% U subset of XU, 2614: ?line {ok, []} = xref:q(S, "U - XU"), 2615: 2616: %% LU = range LC 2617: ?line {ok, []} = xref:q(S, "(LU - range LC) + (range LC - LU)"), 2618: 2619: %% XU = range XC 2620: ?line {ok, []} = xref:q(S, "(XU - range XC) + (range XC - XU)"), 2621: 2622: %% LU subset F 2623: ?line {ok, []} = xref:q(S, "LU - F"), 2624: 2625: %% UU subset F 2626: ?line {ok, []} = xref:q(S, "UU - F"), 2627: 2628: %% ME = (Mod) E 2629: ?line {ok, ME} = xref:q(S, "ME"), 2630: ?line {ok, ME} = xref:q(S, "(Mod) E"), 2631: 2632: %% AE = (App) E 2633: ?line {ok, AE} = xref:q(S, "AE"), 2634: ?line {ok, AE} = xref:q(S, "(App) E"), 2635: 2636: %% RE = (Rel) E 2637: ?line {ok, RE} = xref:q(S, "RE"), 2638: ?line {ok, RE} = xref:q(S, "(Rel) E"), 2639: 2640: %% (Mod) V subset of M 2641: ?line {ok, []} = xref:q(S, "(Mod) V - M"), 2642: 2643: %% range UC subset of U 2644: ?line {ok, []} = xref:q(S, "range UC - U"), 2645: 2646: %% Some checks on the numbers returned by the info functions. 2647: 2648: ?line {Resolved, Unresolved} = info(Info, no_calls), 2649: ?line AllCalls = Resolved + Unresolved, 2650: ?line {ok, AllCalls} = xref:q(S, "# (XLin) E + # (LLin) E"), 2651: 2652: ?line {Local, Exported} = info(Info, no_functions), 2653: ?line LX = Local+Exported, 2654: ?line {ok, LXs} = xref:q(S, 'Extra = _:module_info/"(0|1)" + LM, 2655: # (F - Extra)'), 2656: ?line true = LX =:= LXs, 2657: 2658: ?line {LocalCalls, ExternalCalls, UnresCalls} = 2659: info(Info, no_function_calls), 2660: ?line LEU = LocalCalls + ExternalCalls + UnresCalls, 2661: ?line {ok, LEU} = xref:q(S, "# LC + # XC"), 2662: 2663: ?line InterFunctionCalls = info(Info, no_inter_function_calls), 2664: ?line {ok, InterFunctionCalls} = xref:q(S, "# EE"), 2665: 2666: %% And some more checks on counters... 2667: ?line check_count(S), 2668: 2669: %% ... and more 2670: ?line {ok, []} = xref:q(S, "LM - X - U - B"), 2671: 2672: ok. 2673: 2674: modules_mode_check(S, Info) -> 2675: %% B subset of XU, 2676: ?line {ok, []} = xref:q(S, "B - XU"), 2677: 2678: %% M = AM + LM + UM 2679: ?line {ok, M} = xref:q(S, "M"), 2680: ?line {ok, M} = xref:q(S, "AM + LM + UM"), 2681: 2682: %% DF is a subset of X U B, etc. 2683: ?line {ok, []} = xref:q(S, "DF - X - B"), 2684: ?line {ok, []} = xref:q(S, "DF_3 - DF"), 2685: ?line {ok, []} = xref:q(S, "DF_2 - DF_3"), 2686: ?line {ok, []} = xref:q(S, "DF_1 - DF_2"), 2687: 2688: %% AM, LM and UM are disjoint. 2689: ?line {ok, []} = xref:q(S, "AM * LM + AM * UM + LM * UM"), 2690: 2691: %% (App) M subset of A 2692: ?line {ok, []} = xref:q(S, "(App) M - A"), 2693: 2694: ?line AM = info(Info, no_analyzed_modules), 2695: ?line {ok, AM} = xref:q(S, "# AM"), 2696: 2697: ?line A = info(Info, no_applications), 2698: ?line {ok, A} = xref:q(S, "# A"), 2699: 2700: ?line NoR = info(Info, no_releases), 2701: ?line {ok, NoR} = xref:q(S, "# R"), 2702: 2703: ok. 2704: 2705: %% Checks the counters of some of the overall and modules info functions. 2706: %% (Applications and releases are not checked.) 2707: check_count(S) -> 2708: %%{ok, R} = xref:q(S, 'R'), 2709: %% {ok, A} = xref:q(S, 'A'), 2710: {ok, M} = xref:q(S, 'AM'), 2711: 2712: {ok, _} = xref:q(S, 2713: "Extra := _:module_info/\"(0|1)\" + LM"), 2714: 2715: %% info/1: 2716: {ok, NoR} = xref:q(S, '# R'), 2717: {ok, NoA} = xref:q(S, '# A'), 2718: {ok, NoM} = xref:q(S, '# AM'), 2719: {ok, NoCalls} = xref:q(S, '# (XLin) E + # (LLin) E'), 2720: {ok, NoFunCalls} = xref:q(S, '# E'), 2721: {ok, NoXCalls} = xref:q(S, '# XC'), 2722: {ok, NoLCalls} = xref:q(S, '# LC'), 2723: {ok, NoLXCalls} = xref:q(S, '# (XC * LC)'), 2724: NoAllCalls = NoXCalls + NoLCalls, 2725: {ok, NoFun} = xref:q(S, '# (F - Extra)'), 2726: {ok, NoICalls} = xref:q(S, '# EE'), 2727: 2728: Info = xref:info(S), 2729: NoR = info(Info, no_releases), 2730: NoA = info(Info, no_applications), 2731: NoM = info(Info, no_analyzed_modules), 2732: {NoResolved, NoUC} = info(Info, no_calls), 2733: NoCalls = NoResolved + NoUC, 2734: {NoLocal, NoExternal, NoUnres} = info(Info, no_function_calls), 2735: NoAllCalls = NoLocal + NoExternal + NoUnres, 2736: NoAllCalls = NoFunCalls + NoLXCalls, 2737: {NoLocalFuns, NoExportedFuns} = info(Info, no_functions), 2738: NoFun = NoLocalFuns + NoExportedFuns, 2739: NoICalls = info(Info, no_inter_function_calls), 2740: 2741: %% per module 2742: info_module(M, S), 2743: 2744: ok. 2745: 2746: info_module([M | Ms], S) -> 2747: {ok, NoCalls} = per_module("T = (E | ~p : Mod), # (XLin) T + # (LLin) T", 2748: M, S), 2749: {ok, NoFunCalls} = per_module("# (E | ~p : Mod)", M, S), 2750: {ok, NoXCalls} = per_module("# (XC | ~p : Mod)", M, S), 2751: {ok, NoLCalls} = per_module("# (LC | ~p : Mod)", M, S), 2752: {ok, NoLXCalls} = per_module("# ((XC * LC) | ~p : Mod)", M, S), 2753: NoAllCalls = NoXCalls + NoLCalls, 2754: {ok, NoFun} = per_module("# (F * ~p : Mod - Extra)", M, S), 2755: {ok, NoICalls} = per_module("# (EE | ~p : Mod)", M, S), 2756: 2757: [{_M,Info}] = xref:info(S, modules, M), 2758: {NoResolved, NoUC} = info(Info, no_calls), 2759: NoCalls = NoResolved + NoUC, 2760: {NoLocal, NoExternal, NoUnres} = info(Info, no_function_calls), 2761: NoAllCalls = NoLocal + NoExternal + NoUnres, 2762: NoAllCalls = NoFunCalls + NoLXCalls, 2763: {NoLocalFuns, NoExportedFuns} = info(Info, no_functions), 2764: NoFun = NoLocalFuns + NoExportedFuns, 2765: NoICalls = info(Info, no_inter_function_calls), 2766: 2767: info_module(Ms, S); 2768: info_module([], _S) -> 2769: ok. 2770: 2771: per_module(Q, M, S) -> 2772: xref:q(S, f(Q, [M])). 2773: 2774: info(Info, What) -> 2775: {value, {What, Value}} = lists:keysearch(What, 1, Info), 2776: Value. 2777: 2778: f(S, A) -> 2779: flatten(io_lib:format(S, A)). 2780: 2781: fatom(R) -> 2782: list_to_atom(fstring(R)). 2783: 2784: fstring(R) -> 2785: flatten(xref:format_error(R)). 2786: 2787: start(Server) -> 2788: ?line case xref:start(Server) of 2789: {error, {already_started, _Pid}} -> 2790: ?line xref:stop(Server), 2791: ?line xref:start(Server); 2792: R -> R 2793: end. 2794: 2795: add_erts_code_path(KernelPath) -> 2796: VersionDirs = 2797: filelib:is_dir( 2798: filename:join( 2799: [code:lib_dir(), 2800: lists:flatten( 2801: ["kernel-", 2802: [X || 2803: {kernel,_,X} <- 2804: application_controller:which_applications()]])])), 2805: case VersionDirs of 2806: true -> 2807: case code:lib_dir(erts) of 2808: String when is_list(String) -> 2809: [KernelPath, fname(String,"ebin")]; 2810: _Other1 -> 2811: [KernelPath] 2812: end; 2813: false -> 2814: % Clearcase? 2815: PrelPath = filename:join([code:lib_dir(),"..","erts","preloaded"]), 2816: case filelib:is_dir(PrelPath) of 2817: true -> 2818: [KernelPath, fname(PrelPath,"ebin")]; 2819: false -> 2820: [KernelPath] 2821: end 2822: end. 2823: 2824: