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: