1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2009-2018. 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%%% File: ct_log_SUITE 23%%% 24%%% Description: Test that ct:log, ct:pal and io:format print to 25%%% the test case log file as expected, with or without special HTML 26%%% characters being escaped. 27%%% 28%%%------------------------------------------------------------------- 29-module(ct_log_SUITE). 30 31-compile(export_all). 32 33-include_lib("common_test/include/ct.hrl"). 34-include_lib("common_test/include/ct_event.hrl"). 35 36-define(eh, ct_test_support_eh). 37 38%%-------------------------------------------------------------------- 39%% TEST SERVER CALLBACK FUNCTIONS 40%%-------------------------------------------------------------------- 41init_per_suite(Config) -> 42 Config. 43 44end_per_suite(_Config) -> 45 ok. 46 47init_per_testcase(_TestCase, Config) -> 48 Config. 49 50end_per_testcase(_TestCase, _Config) -> 51 ok. 52 53suite() -> [{ct_hooks,[ts_install_cth]}]. 54 55all() -> 56 [{group,print_and_verify}]. 57 58groups() -> 59 [{print_and_verify,[sequence],[print,verify]}]. 60 61init_per_group(_GroupName, Config) -> 62 Config. 63 64end_per_group(_GroupName, Config) -> 65 Config. 66 67%%-------------------------------------------------------------------- 68%% TEST CASES 69%%-------------------------------------------------------------------- 70 71%%%----------------------------------------------------------------- 72%%% 73print(Config) -> 74 TcLogFile = proplists:get_value(tc_logfile, Config), 75 Pid = self(), 76 String = atom_to_list(?MODULE), 77 78 %% START mark 79 io:format("LOGGING START~n"), 80 81 %% io:format 82 io:format("1. Printing nothing~n", []), 83 io:format("2. Printing a string: ~s~n", [String]), 84 io:format("3. Printing a string: ~p~n", [String]), 85 io:format("4. Printing a tuple: ~w~n", [{module,?MODULE}]), 86 io:format("5. Printing a pid: ~w~n", [Pid]), 87 io:format("6. Printing HTML: <pre>~s</pre>~n", [String]), 88 89 %% ct:pal 90 ct:pal("1. Printing nothing"), 91 ct:pal("2. Printing nothing", []), 92 ct:pal("3. Printing a string: ~s", [String]), 93 ct:pal("4. Printing a string: ~p", [String]), 94 ct:pal("5. Printing a tuple: ~w", [{module,?MODULE}]), 95 ct:pal("6. Printing a pid: ~w", [Pid]), 96 ct:pal("7. Printing HTML: <pre>~s</pre>", [String]), 97 ct:pal(ct_internal, "8. Printing with category"), 98 ct:pal(ct_internal, "9. Printing with ~s", ["category"]), 99 ct:pal(50, "10. Printing with importance"), 100 ct:pal(50, "11. Printing with ~s", ["importance"]), 101 ct:pal(ct_internal, 50, "12. Printing with ~s", ["category and importance"]), 102 103 ct:pal("13. Printing with heading", [], 104 [{heading,"This is a heading"}]), 105 ct:pal(ct_internal, "14. Printing with category and heading", [], 106 [{heading,"This is a heading"}]), 107 ct:pal(50, "15. Printing with importance and heading", [], 108 [{heading,"This is a heading"}]), 109 ct:pal(ct_internal, 50, "16. Printing with category, importance and heading", [], 110 [{heading,"This is a heading"}]), 111 112 %% ct:log 113 ct:log("1. Printing nothing"), 114 ct:log("2. Printing nothing", []), 115 ct:log("3. Printing a string: ~s", [String]), 116 ct:log("4. Printing a string: ~p", [String]), 117 ct:log("5. Printing a tuple: ~w", [{module,?MODULE}]), 118 ct:log("6. Printing a pid: ~w", [Pid]), 119 ct:log("7. Printing HTML: <pre>~s</pre>", [String]), 120 ct:log("8. Printing a pid escaped: ~w", [Pid], [esc_chars]), 121 ct:log("9. Printing a string escaped: ~p", [String], [esc_chars]), 122 ct:log("10. Printing HTML escaped: <pre>~s</pre>", [String], [esc_chars]), 123 ct:log("11. Printing a string, no css: ~s", [String], [no_css]), 124 ct:log("12. Printing a pid escaped, no css: ~w", [Pid], 125 [esc_chars, no_css]), 126 ct:log(ct_internal, "13. Printing with category"), 127 ct:log(ct_internal, "14. Printing with ~s", ["category"]), 128 ct:log(ct_internal, "15. Printing with ~s, no_css", ["category"], 129 [no_css]), 130 ct:log(50, "16. Printing with importance"), 131 ct:log(50, "17. Printing with ~s", ["importance"]), 132 ct:log(50, "18. Printing with ~s, no_css", ["importance"], [no_css]), 133 ct:log(ct_internal, 50, "19. Printing with category and importance"), 134 ct:log(ct_internal, 50, "20. Printing with ~s", ["category and importance"]), 135 ct:log(ct_internal, 50, "21. Printing a pid escaped with ~s, no_css: ~w", 136 ["category and importance",Pid], [esc_chars,no_css]), 137 138 ct:log("22. Printing with heading", [], 139 [{heading,"This is a heading"}]), 140 ct:log(ct_internal, "23. Printing with category and heading", [], 141 [{heading,"This is a heading"}]), 142 ct:log(50, "24. Printing with importance and heading", [], 143 [{heading,"This is a heading"}]), 144 ct:log(ct_internal, 50, "25. Printing with category, importance and heading", [], 145 [{heading,"This is a heading"}]), 146 147 %% END mark 148 ct:log("LOGGING END", [], [no_css]), 149 150 151 %% ct:print 152 ct:print("1. Does this show??"), 153 ct:print("2. Does this ~s", ["show??"]), 154 ct:print("3. Is this a non-html pid?? ~w", [self()]), 155 ct:print(ct_internal, "4. Printing with category"), 156 ct:print(ct_internal, "5. Printing with ~s", ["category"]), 157 ct:print(50, "6. Printing with importance"), 158 ct:print(50, "7. Printing with ~s", ["importance"]), 159 ct:print(ct_internal, 50, "8. Printing with ~s", ["category and importance"]), 160 ct:print("9. Printing with heading", [], 161 [{heading,"This is a heading"}]), 162 ct:print(ct_internal, "10. Printing with category and heading", [], 163 [{heading,"This is a heading"}]), 164 ct:print(50, "11. Printing with importance and heading", [], 165 [{heading,"This is a heading"}]), 166 ct:print(ct_internal, 50, "12. Printing with category, importance and heading", [], 167 [{heading,"This is a heading"}]), 168 169 {save_config,[{the_logfile,TcLogFile},{the_pid,Pid},{the_string,String}]}. 170 171 172verify(Config) -> 173 {print,SavedCfg} = proplists:get_value(saved_config, Config), 174 TcLogFile = proplists:get_value(the_logfile, SavedCfg), 175 Pid = proplists:get_value(the_pid, SavedCfg), 176 StrPid = lists:flatten(io_lib:format("~p",[Pid])), 177 EscPid = "<" ++ string:slice(StrPid, 1, length(StrPid)-2) ++ ">", 178 String = proplists:get_value(the_string, SavedCfg), 179 ct:log("Read from prev testcase: ~p & ~p", [TcLogFile,Pid]), 180 {ok,Dev} = file:open(TcLogFile, [read]), 181 ok = read_until(Dev, "LOGGING START\n"), 182 183 ct:pal("VERIFYING LOG ENTRIES...", []), 184 185 %% io:format 186 match_line(Dev, "1. Printing nothing", []), 187 read_nl(Dev), 188 match_line(Dev, "2. Printing a string: ~s", [String]), 189 read_nl(Dev), 190 match_line(Dev, "3. Printing a string: ~p", [String]), 191 read_nl(Dev), 192 match_line(Dev, "4. Printing a tuple: ~w", [{module,?MODULE}]), 193 read_nl(Dev), 194 match_line(Dev, "5. Printing a pid: ~s", [EscPid]), 195 read_nl(Dev), 196 match_line(Dev, "6. Printing HTML: <pre>~s</pre>", [String]), 197 read_nl(Dev), 198 199 %% ct:pal 200 read_header(Dev), 201 match_line(Dev, "1. Printing nothing", []), 202 read_footer(Dev), 203 read_header(Dev), 204 match_line(Dev, "2. Printing nothing", []), 205 read_footer(Dev), 206 read_header(Dev), 207 match_line(Dev, "3. Printing a string: ~s", [String]), 208 read_footer(Dev), 209 read_header(Dev), 210 match_line(Dev, "4. Printing a string: ~p", [String]), 211 read_footer(Dev), 212 read_header(Dev), 213 match_line(Dev, "5. Printing a tuple: ~w", [{module,?MODULE}]), 214 read_footer(Dev), 215 read_header(Dev), 216 match_line(Dev, "6. Printing a pid: ~s", [EscPid]), 217 read_footer(Dev), 218 read_header(Dev), 219 match_line(Dev, "7. Printing HTML: <pre>~s</pre>", [String]), 220 read_footer(Dev), 221 read_header(Dev, "\"ct_internal\""), 222 match_line(Dev, "8. Printing with category", []), 223 read_footer(Dev), 224 read_header(Dev, "\"ct_internal\""), 225 match_line(Dev, "9. Printing with ~s", ["category"]), 226 read_footer(Dev), 227 read_header(Dev), 228 match_line(Dev, "10. Printing with importance", []), 229 read_footer(Dev), 230 read_header(Dev), 231 match_line(Dev, "11. Printing with ~s", ["importance"]), 232 read_footer(Dev), 233 read_header(Dev, "\"ct_internal\""), 234 match_line(Dev, "12. Printing with ~s", ["category and importance"]), 235 read_footer(Dev), 236 read_header(Dev, "\"default\"", "This is a heading"), 237 match_line(Dev, "13. Printing with heading", []), 238 read_footer(Dev), 239 read_header(Dev, "\"ct_internal\"", "This is a heading"), 240 match_line(Dev, "14. Printing with category and heading", []), 241 read_footer(Dev), 242 read_header(Dev, "\"default\"", "This is a heading"), 243 match_line(Dev, "15. Printing with importance and heading", []), 244 read_footer(Dev), 245 read_header(Dev, "\"ct_internal\"", "This is a heading"), 246 match_line(Dev, "16. Printing with category, importance and heading", []), 247 read_footer(Dev), 248 249 %% ct:log 250 read_header(Dev), 251 match_line(Dev, "1. Printing nothing", []), 252 read_footer(Dev), 253 read_header(Dev), 254 match_line(Dev, "2. Printing nothing", []), 255 read_footer(Dev), 256 read_header(Dev), 257 match_line(Dev, "3. Printing a string: ~s", [String]), 258 read_footer(Dev), 259 read_header(Dev), 260 match_line(Dev, "4. Printing a string: ~p", [String]), 261 read_footer(Dev), 262 read_header(Dev), 263 match_line(Dev, "5. Printing a tuple: ~w", [{module,?MODULE}]), 264 read_footer(Dev), 265 read_header(Dev), 266 match_line(Dev, "6. Printing a pid: ~w", [Pid]), 267 read_footer(Dev), 268 read_header(Dev), 269 match_line(Dev, "7. Printing HTML: <pre>~s</pre>", [String]), 270 read_footer(Dev), 271 read_header(Dev), 272 match_line(Dev, "8. Printing a pid escaped: ~s", [EscPid]), 273 read_footer(Dev), 274 read_header(Dev), 275 match_line(Dev, "9. Printing a string escaped: ~p", [String]), 276 read_footer(Dev), 277 read_header(Dev), 278 match_line(Dev, "10. Printing HTML escaped: <pre>~s</pre>", 279 [String]), 280 read_footer(Dev), 281 match_line(Dev, "11. Printing a string, no css: ~s", [String]), 282 match_line(Dev, "12. Printing a pid escaped, no css: ~s", [EscPid]), 283 read_header(Dev, "\"ct_internal\""), 284 match_line(Dev, "13. Printing with category", []), 285 read_footer(Dev), 286 read_header(Dev, "\"ct_internal\""), 287 match_line(Dev, "14. Printing with ~s", ["category"]), 288 read_footer(Dev), 289 match_line(Dev, "15. Printing with ~s, no_css", ["category"]), 290 read_header(Dev), 291 match_line(Dev, "16. Printing with importance", []), 292 read_footer(Dev), 293 read_header(Dev), 294 match_line(Dev, "17. Printing with ~s", ["importance"]), 295 read_footer(Dev), 296 match_line(Dev, "18. Printing with ~s, no_css", ["importance"]), 297 read_header(Dev, "\"ct_internal\""), 298 match_line(Dev, "19. Printing with category and importance", []), 299 read_footer(Dev), 300 read_header(Dev, "\"ct_internal\""), 301 match_line(Dev, "20. Printing with ~s", ["category and importance"]), 302 read_footer(Dev), 303 match_line(Dev, "21. Printing a pid escaped with ~s, no_css: ~s", 304 ["category and importance",EscPid]), 305 read_header(Dev, "\"default\"", "This is a heading"), 306 match_line(Dev, "22. Printing with heading", []), 307 read_footer(Dev), 308 read_header(Dev, "\"ct_internal\"", "This is a heading"), 309 match_line(Dev, "23. Printing with category and heading", []), 310 read_footer(Dev), 311 read_header(Dev, "\"default\"", "This is a heading"), 312 match_line(Dev, "24. Printing with importance and heading", []), 313 read_footer(Dev), 314 read_header(Dev, "\"ct_internal\"", "This is a heading"), 315 match_line(Dev, "25. Printing with category, importance and heading", []), 316 read_footer(Dev), 317 file:close(Dev), 318 ok. 319 320%%%----------------------------------------------------------------- 321%%% HELP FUNCTIONS 322%%%----------------------------------------------------------------- 323 324read_until(Dev, Pat) -> 325 case file:read_line(Dev) of 326 {ok,Pat} -> 327 file:read_line(Dev), % \n 328 ok; 329 eof -> 330 file:close(Dev), 331 {error,{not_found,Pat}}; 332 _ -> 333 read_until(Dev, Pat) 334 end. 335 336match_line(Dev, Format, Args) -> 337 Pat = lists:flatten(io_lib:format(Format, Args)), 338 Line = element(2, file:read_line(Dev)), 339 340 %% for debugging purposes: 341 ct:pal("L: ~tp", [Line], [no_css]), 342 343 case re:run(Line, Pat) of 344 {match,_} -> 345 ok; 346 nomatch -> 347 ct:pal("ERROR! No match for ~p", [Pat]), 348 file:close(Dev), 349 ct:fail({mismatch,Pat,Line}) 350 end. 351 352read_header(Dev) -> 353 read_header(Dev, "\"default\"", "User"). 354 355read_header(Dev, Cat) -> 356 read_header(Dev, Cat, "User"). 357 358read_header(Dev, Cat, Heading) -> 359 file:read_line(Dev), % \n 360 "</pre>\n" = element(2, file:read_line(Dev)), 361 {ok,Hd} = file:read_line(Dev), 362 363 %% for debugging purposes: 364 ct:pal("H: ~tp", [Hd], [no_css]), 365 366 Pat = "<div class="++Cat++"><pre><b>"++ 367 "\\*\\*\\* "++Heading++" \\d{4}-\\d{2}-\\d{2} "++ 368 "\\d{2}:\\d{2}:\\d{2}.\\d{1,} \\*\\*\\*</b>", 369 370 case re:run(Hd, Pat) of 371 {match,_} -> 372 ok; 373 _ -> 374 ct:pal("ERROR! No match for ~p", [Pat]), 375 file:close(Dev), 376 ct:fail({mismatch,Pat,Hd}) 377 end. 378 379read_footer(Dev) -> 380 "</pre></div>\n" = element(2, file:read_line(Dev)), 381 "<pre>\n" = element(2, file:read_line(Dev)), 382 %% for debugging purposes: 383 ct:pal("F: </pre></div><pre>", [], [no_css]). 384 385read_nl(Dev) -> 386 file:read_line(Dev). 387 388 389