1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2005-2017. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20%%
21%%----------------------------------------------------------------------
22%% Purpose: Verify the application specifics of the asn1 application
23%%----------------------------------------------------------------------
24-module(asn1_app_SUITE).
25-export([all/0,groups/0,init_per_group/2,end_per_group/2,
26         init_per_suite/1,end_per_suite/1,
27         appup/1,fields/1,modules/1,export_all/1,app_depend/1]).
28
29%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
30
31all() ->
32    [appup, fields, modules, export_all, app_depend].
33
34groups() ->
35    [].
36
37init_per_group(_GroupName, Config) ->
38    Config.
39
40end_per_group(_GroupName, Config) ->
41    Config.
42
43
44%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
45
46init_per_suite(Config) when is_list(Config) ->
47    case is_app(asn1) of
48	{ok, AppFile} ->
49	    io:format("AppFile: ~n~p~n", [AppFile]),
50	    [{app_file, AppFile}|Config];
51	{error, Reason} ->
52	    fail(Reason)
53    end.
54
55is_app(App) ->
56    LibDir = code:lib_dir(App),
57    File = filename:join([LibDir, "ebin", atom_to_list(App) ++ ".app"]),
58    case file:consult(File) of
59	{ok, [{application, App, AppFile}]} ->
60	    {ok, AppFile};
61	Error ->
62	    {error, {invalid_format, Error}}
63    end.
64
65
66end_per_suite(Config) when is_list(Config) ->
67    Config.
68
69%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
70
71appup(Config) when is_list(Config) ->
72    ok = test_server:appup_test(asn1).
73
74%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75
76fields(Config) when is_list(Config) ->
77    AppFile = key1find(app_file, Config),
78    Fields = [vsn, description, modules, registered, applications],
79    case check_fields(Fields, AppFile, []) of
80	[] ->
81	    ok;
82	Missing ->
83	    fail({missing_fields, Missing})
84    end.
85
86check_fields([], _AppFile, Missing) ->
87    Missing;
88check_fields([Field|Fields], AppFile, Missing) ->
89    check_fields(Fields, AppFile, check_field(Field, AppFile, Missing)).
90
91check_field(Name, AppFile, Missing) ->
92    io:format("checking field: ~p~n", [Name]),
93    case lists:keymember(Name, 1, AppFile) of
94	true ->
95	    Missing;
96	false ->
97	    [Name|Missing]
98    end.
99
100
101%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102
103modules(Config) when is_list(Config) ->
104    AppFile  = key1find(app_file, Config),
105    Mods     = key1find(modules, AppFile),
106    EbinList = get_ebin_mods(asn1),
107    case missing_modules(Mods, EbinList, []) of
108	[] ->
109	    ok;
110	Missing ->
111	    throw({error, {missing_modules, Missing}})
112    end,
113    case extra_modules(Mods, EbinList, []) of
114	[] ->
115	    ok;
116	Extra ->
117	    check_asn1ct_modules(Extra)
118    end,
119    {ok, Mods}.
120
121get_ebin_mods(App) ->
122    LibDir  = code:lib_dir(App),
123    EbinDir = filename:join([LibDir,"ebin"]),
124    {ok, Files0} = file:list_dir(EbinDir),
125    Files1 = [lists:reverse(File) || File <- Files0],
126    [list_to_atom(lists:reverse(Name)) || [$m,$a,$e,$b,$.|Name] <- Files1].
127
128check_asn1ct_modules(Extra) ->
129    ASN1CTMods = [asn1ct,asn1ct_check,asn1_db,asn1ct_pretty_format,
130		  asn1ct_gen,asn1ct_gen_check,asn1ct_gen_per,
131		  asn1ct_name,asn1ct_constructed_per,asn1ct_constructed_ber,
132		  asn1ct_gen_ber,asn1ct_constructed_ber_bin_v2,
133		  asn1ct_gen_ber_bin_v2,asn1ct_value,
134		  asn1ct_tok,asn1ct_parser2,asn1ct_table,
135		  asn1ct_imm,asn1ct_func,asn1ct_rtt,
136		  asn1ct_eval_ext],
137    case Extra -- ASN1CTMods of
138	[] ->
139	    ok;
140	Extra2 ->
141	    throw({error, {extra_modules, Extra2}})
142    end.
143
144missing_modules([], _Ebins, Missing) ->
145    Missing;
146missing_modules([Mod|Mods], Ebins, Missing) ->
147    case lists:member(Mod, Ebins) of
148	true ->
149	    missing_modules(Mods, Ebins, Missing);
150	false ->
151	    io:format("missing module: ~p~n", [Mod]),
152	    missing_modules(Mods, Ebins, [Mod|Missing])
153    end.
154
155
156extra_modules(_Mods, [], Extra) ->
157    Extra;
158extra_modules(Mods, [Mod|Ebins], Extra) ->
159    case lists:member(Mod, Mods) of
160	true ->
161	    extra_modules(Mods, Ebins, Extra);
162	false ->
163	    io:format("supefluous module: ~p~n", [Mod]),
164	    extra_modules(Mods, Ebins, [Mod|Extra])
165    end.
166
167
168%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
169
170
171export_all(Config) when is_list(Config) ->
172    AppFile = key1find(app_file, Config),
173    Mods    = key1find(modules, AppFile),
174    check_export_all(Mods).
175
176
177check_export_all([]) ->
178    ok;
179check_export_all([Mod|Mods]) ->
180    case (catch apply(Mod, module_info, [compile])) of
181	{'EXIT', {undef, _}} ->
182	    check_export_all(Mods);
183	O ->
184            case lists:keyfind(options, 1, O) of
185                false ->
186                    check_export_all(Mods);
187                {options, List} ->
188                    case lists:member(export_all, List) of
189                        true ->
190			    throw({error, {export_all, Mod}});
191			false ->
192			    check_export_all(Mods)
193                    end
194            end
195    end.
196
197
198%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
199
200app_depend(Config) when is_list(Config) ->
201    AppFile = key1find(app_file, Config),
202    Apps    = key1find(applications, AppFile),
203    check_apps(Apps).
204
205
206check_apps([]) ->
207    ok;
208check_apps([App|Apps]) ->
209    case is_app(App) of
210	{ok, _} ->
211	    check_apps(Apps);
212	Error ->
213	    throw({error, {missing_app, {App, Error}}})
214    end.
215
216
217%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
218
219
220fail(Reason) ->
221    exit({suite_failed, Reason}).
222
223key1find(Key, L) ->
224    case lists:keyfind(Key, 1, L) of
225	false ->
226	    fail({not_found, Key, L});
227	{Key, Value} ->
228	    Value
229    end.
230