1%%-----------------------------------------------------------------------
2%%
3%% %CopyrightBegin%
4%%
5%% Copyright Ericsson AB 2000-2016. All Rights Reserved.
6%%
7%% Licensed under the Apache License, Version 2.0 (the "License");
8%% you may not use this file except in compliance with the License.
9%% You may obtain a copy of the License at
10%%
11%%     http://www.apache.org/licenses/LICENSE-2.0
12%%
13%% Unless required by applicable law or agreed to in writing, software
14%% distributed under the License is distributed on an "AS IS" BASIS,
15%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16%% See the License for the specific language governing permissions and
17%% limitations under the License.
18%%
19%% %CopyrightEnd%
20%%
21%%
22%%----------------------------------------------------------------------
23%% File    : fileTransfer_SUITE.erl
24%% Purpose :
25%%----------------------------------------------------------------------
26
27-module(fileTransfer_SUITE).
28
29%%--------------- INCLUDES -----------------------------------
30-include_lib("cosFileTransfer/src/cosFileTransferApp.hrl").
31
32-include_lib("common_test/include/ct.hrl").
33
34%%--------------- DEFINES ------------------------------------
35-define(default_timeout, test_server:minutes(20)).
36-define(match(ExpectedRes, Expr),
37        fun() ->
38               AcTuAlReS = (catch (Expr)),
39               case AcTuAlReS of
40                   ExpectedRes ->
41                       io:format("------ CORRECT RESULT ------~n~p~n",
42                                 [AcTuAlReS]),
43                       AcTuAlReS;
44                   _ ->
45                       io:format("###### ERROR ERROR ######~n~p~n",
46                                 [AcTuAlReS]),
47                       exit(AcTuAlReS)
48               end
49       end()).
50
51-define(matchnopr(ExpectedRes, Expr),
52        fun() ->
53               AcTuAlReS = (catch (Expr)),
54               case AcTuAlReS of
55                   ExpectedRes ->
56                       io:format("------ CORRECT RESULT (~p) ------~n", [?LINE]),
57                       AcTuAlReS;
58                   _ ->
59                       io:format("###### ERROR ERROR ######~n~p~n",
60                                 [AcTuAlReS]),
61                       exit(AcTuAlReS)
62               end
63       end()).
64
65
66
67
68
69%%-----------------------------------------------------------------
70%% External exports
71%%-----------------------------------------------------------------
72-export([all/0,suite/0,groups/0,
73	 init_per_group/2,end_per_group/2,
74	 cases/0,
75	 init_per_suite/1,
76	 end_per_suite/1,
77	 fileIterator_api/1,
78	 fts_ftp_file_api/1,
79	 fts_ftp_file_ssl_api/1,
80	 fts_ftp_dir_api/1,
81	 fts_native_file_api/1,
82	 fts_native_file_ssl_api/1,
83	 fts_native_dir_api/1,
84	 init_per_testcase/2,
85	 end_per_testcase/2,
86	 install_data/2,
87	 uninstall_data/1,
88	 slave_sup/0,
89	 app_test/1]).
90
91%%-----------------------------------------------------------------
92%% Func: all/1
93%% Args:
94%% Returns:
95%%-----------------------------------------------------------------
96suite() ->
97    [{ct_hooks,[ts_install_cth]}].
98
99all() ->
100    cases().
101
102groups() ->
103    [].
104
105
106
107init_per_group(_GroupName, Config) ->
108    Config.
109
110end_per_group(_GroupName, Config) ->
111    Config.
112
113
114cases() ->
115    [fts_ftp_dir_api, fts_ftp_file_api,
116     fts_ftp_file_ssl_api, fts_native_dir_api,
117     fts_native_file_api, fts_native_file_ssl_api,
118     fileIterator_api, app_test].
119
120%%-----------------------------------------------------------------
121%% Init and cleanup functions.
122%%-----------------------------------------------------------------
123
124init_per_testcase(_Case, Config) ->
125    Dog=test_server:timetrap(?default_timeout),
126    [{watchdog, Dog}|Config].
127
128
129end_per_testcase(_Case, Config) ->
130    Dog = proplists:get_value(watchdog, Config),
131    test_server:timetrap_cancel(Dog),
132    ok.
133
134init_per_suite(Config) ->
135    case crypto_works() of
136	false ->
137	    {skip,"Could not start crypto!"};
138	true ->
139	    orber:jump_start(),
140	    cosProperty:install(),
141	    cosProperty:start(),
142	    Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
143	    %% Client
144	    cosFileTransferApp:configure(ssl_client_certfile,
145					 filename:join([Dir, "client", "cert.pem"])),
146	    cosFileTransferApp:configure(ssl_client_cacertfile,
147					 filename:join([Dir, "client", "cacerts.pem"])),
148	    cosFileTransferApp:configure(ssl_client_verify, 1),
149	    cosFileTransferApp:configure(ssl_client_depth, 0),
150	    %% Server
151	    cosFileTransferApp:configure(ssl_server_certfile,
152					 filename:join([Dir, "server", "cert.pem"])),
153	    cosFileTransferApp:configure(ssl_server_cacertfile,
154					 filename:join([Dir, "server", "cacerts.pem"])),
155	    cosFileTransferApp:configure(ssl_server_verify, 1),
156	    cosFileTransferApp:configure(ssl_server_depth, 0),
157	    crypto:start(),
158	    ssl:start(),
159	    cosFileTransferApp:install(),
160	    cosFileTransferApp:start(),
161	    if
162		is_list(Config) ->
163		    Config;
164		true ->
165		    exit("Config not a list")
166	    end
167    end.
168
169crypto_works() ->
170    try crypto:start() of
171	{error,{already_started,crypto}} -> true;
172	ok -> true
173    catch
174	error:_ ->
175	    false
176    end.
177
178end_per_suite(Config) ->
179    ssl:stop(),
180    crypto:stop(),
181    cosFileTransferApp:stop(),
182    cosProperty:stop(),
183    cosProperty:uninstall(),
184    cosFileTransferApp:uninstall(),
185    orber:jump_stop(),
186    Config.
187
188%%-----------------------------------------------------------------
189%%  Local definitions
190%%-----------------------------------------------------------------
191-define(FTP_USER, "anonymous").
192-define(FTP_PASS, "fileTransfer_SUITE@localhost").
193-define(TEST_DIR,["/", "incoming"]).
194
195-define(FTP_PORT, 21).
196-define(FTP_ACC,  "anonymous").
197
198-define(BAD_HOST, "badhostname").
199-define(BAD_USER, "baduser").
200-define(BAD_DIR,  "baddirectory").
201
202-define(TEST_FILE_DATA,   "If this file exists after a completed test an error occurred.").
203-define(TEST_FILE_DATA2,  "1234567890123").
204
205%%-----------------------------------------------------------------
206%%  aoo-file test
207%%-----------------------------------------------------------------
208app_test(_Config) ->
209    ok=?t:app_test(cosFileTransfer),
210    ok.
211
212%%-----------------------------------------------------------------
213%%  FileIterator API tests
214%%-----------------------------------------------------------------
215fileIterator_api(Config) ->
216    case ftp_host(Config) of
217	{skipped, SkippedReason} ->
218	    {skipped, SkippedReason};
219	Host ->
220
221	    {ok, Node} = create_node("fileIterator_api", 4008, normal),
222	    ?match(ok, remote_apply(Node, ?MODULE, install_data,
223					  [tcp, {{'NATIVE',
224						  'cosFileTransferNATIVE_file'}, Host,
225						 "fileIterator_api"}])),
226
227            %% Create a Virtual File System.
228%%    VFS = ?match({_,_,_,_,_,_},
229%%		 cosFileTransferApp:create_VFS({'NATIVE',
230%%						'cosFileTransferNATIVE_file'},
231%%					       [], Host, ?FTP_PORT)),
232	    VFS = ?matchnopr({'IOP_IOR',"IDL:omg.org/CosFileTransfer/VirtualFileSystem:1.0",_},
233				   corba:string_to_object("corbaname::1.2@localhost:4008/NameService#fileIterator_api")),
234
235            %% Start two File Transfer Sessions (Source and Target).
236	    {FS, Dir} = ?matchnopr({{_,_,_},{_,_,_}},
237			'CosFileTransfer_VirtualFileSystem':login(VFS,
238								  ?FTP_USER,
239								  ?FTP_PASS,
240								  ?FTP_ACC)),
241
242            %% Do some basic test on one of the Directories attributes.
243	    ?match([_H|_], 'CosFileTransfer_Directory':'_get_name'(Dir)),
244	    ?match([_H|_], 'CosFileTransfer_Directory':'_get_complete_file_name'(Dir)),
245	    ?match({'IOP_IOR',[],[]}, 'CosFileTransfer_Directory':'_get_parent'(Dir)),
246	    ?matchnopr(FS, 'CosFileTransfer_Directory':'_get_associated_session'(Dir)),
247	    {ok,[],FileIter} = ?match({ok,[],_}, 'CosFileTransfer_Directory':list(Dir, 0)),
248            %% Usually the working directory for the test is not empty so no need for
249            %% creating files of our own?!
250	    #any{value=Children} = ?match({any, _, _},
251					  'CosPropertyService_PropertySet':
252					  get_property_value(Dir, "num_children")),
253
254	    if
255		Children > 5 ->
256		    ?matchnopr({true, _}, 'CosFileTransfer_FileIterator':next_one(FileIter)),
257		    ?matchnopr({true, _}, 'CosFileTransfer_FileIterator':next_n(FileIter, 3)),
258		    ?matchnopr({true, _}, 'CosFileTransfer_FileIterator':next_n(FileIter,
259										      Children)),
260		    ?matchnopr({false, _}, 'CosFileTransfer_FileIterator':next_one(FileIter)),
261		    ?match({false, []}, 'CosFileTransfer_FileIterator':next_n(FileIter, 1)),
262		    ok;
263		true ->
264	    ok
265	    end,
266	    ?match(ok, 'CosFileTransfer_FileIterator':destroy(FileIter)),
267	    ?match(false, corba_object:non_existent(FS)),
268	    ?match(ok, 'CosFileTransfer_FileTransferSession':logout(FS)),
269            %% To make sure Orber can remove it from mnesia.
270	    timer:sleep(1000),
271	    ?match(true, corba_object:non_existent(FS)),
272	    ?match(ok, remote_apply(Node, ?MODULE, uninstall_data, ["fileIterator_api"])),
273	    stop_orber_remote(Node, normal),
274	    ok
275    end.
276
277
278%%-----------------------------------------------------------------
279%%  FileTransferSession API tests
280%%-----------------------------------------------------------------
281fts_ftp_file_api(Config) ->
282    {ok, Node} = create_node("ftp_file_api", 4004, normal),
283    file_helper(Config, 'FTP', ?TEST_DIR, Node, 4004, "ftp_file_api", tcp).
284
285fts_ftp_file_ssl_api(Config) ->
286    {ok, Node} = create_node("ftp_file_api_ssl", {4005, 1}, ssl),
287    file_helper(Config, 'FTP', ?TEST_DIR, Node, 4005, "ftp_file_api_ssl", ssl).
288
289fts_native_file_api(Config) ->
290    {ok, Node} = create_node("native_file_api", 4006, normal),
291    {ok, Pwd} = file:get_cwd(),
292    file_helper(Config,{'NATIVE', 'cosFileTransferNATIVE_file'},filename:split(Pwd),
293		Node, 4006, "native_file_api", tcp).
294
295fts_native_file_ssl_api(Config) ->
296    {ok, Node} = create_node("native_file_ssl_api", {4007, 1}, ssl),
297    {ok, Pwd} = file:get_cwd(),
298    file_helper(Config,{'NATIVE', 'cosFileTransferNATIVE_file'},filename:split(Pwd),
299	Node, 4007, "native_file_ssl_api", ssl).
300
301
302file_helper(Config, WhichType, TEST_DIR, Node, Port, Name, Type) ->
303    case ftp_host(Config) of
304	{skipped, SkippedReason} ->
305	    {skipped, SkippedReason};
306	Host ->
307	    TEST_SOURCE  = TEST_DIR ++ [create_name(remove_me_source)],
308	    TEST_SOURCE2 = TEST_DIR ++ [create_name(remove_me_source)],
309	    TEST_TARGET  = TEST_DIR ++ [create_name(remove_me_target)],
310
311	    io:format("<<<<<< CosFileTransfer Testing Configuration >>>>>>~n",[]),
312	    io:format("Source: ~p~nTarget: ~p~n", [TEST_SOURCE, TEST_TARGET]),
313
314	    ?match(ok, remote_apply(Node, ?MODULE, install_data,
315					  [Type, {WhichType, Host, Name}])),
316
317	    VFST = ?match({'IOP_IOR',"IDL:omg.org/CosFileTransfer/VirtualFileSystem:1.0",_},
318				corba:string_to_object("corbaname::1.2@localhost:"++integer_to_list(Port)++"/NameService#"++Name)),
319
320
321            %% Create a Virtual File System.
322	    VFS = ?match({_,_,_,_,_,_},
323			       cosFileTransferApp:create_VFS(WhichType, [], Host, ?FTP_PORT,
324							     [{protocol, Type}])),
325            %% Start two File Transfer Sessions (Source and Target).
326	    {FST, _DirT} = ?match({{_,_,_},{_,_,_}},
327					'CosFileTransfer_VirtualFileSystem':login(VFST,
328										  ?FTP_USER,
329										  ?FTP_PASS,
330										  ?FTP_ACC)),
331	    {FSS, DirS} = ?match({{_,_,_,_,_,_},{_,_,_,_,_,_}},
332				       'CosFileTransfer_VirtualFileSystem':login(VFS,
333										 ?FTP_USER,
334										 ?FTP_PASS,
335										 ?FTP_ACC)),
336
337            %% Do some basic test on one of the Directories attributes.
338	    ?match([_H|_], 'CosFileTransfer_Directory':'_get_name'(DirS)),
339	    ?match([_H|_], 'CosFileTransfer_Directory':'_get_complete_file_name'(DirS)),
340	    ?match({'IOP_IOR',[],[]}, 'CosFileTransfer_Directory':'_get_parent'(DirS)),
341	    ?match(FSS, 'CosFileTransfer_Directory':'_get_associated_session'(DirS)),
342
343            %% Get a FileList before we create any new Files
344	    #'CosFileTransfer_FileWrapper'{the_file = Dir} =
345		?match({'CosFileTransfer_FileWrapper', _, ndirectory},
346		       'CosFileTransfer_FileTransferSession':get_file(FSS, TEST_DIR)),
347	    {ok,FileList, Iter1} = ?match({ok,_,_}, 'CosFileTransfer_Directory':list(Dir, 10)),
348	    loop_files(FileList),
349
350	    case Iter1 of
351		{'IOP_IOR',[],[]} ->
352		    ok;
353		_->
354		    ?match(ok, 'CosFileTransfer_FileIterator':destroy(Iter1))
355	    end,
356
357	    #any{value=Count1} = ?match({any, _, _}, 'CosPropertyService_PropertySet':
358					get_property_value(Dir, "num_children")),
359
360            %% Now we want to transfer a file from source to target. First, we'll create
361            %% a a file to work with.
362	    create_file_on_source_node(WhichType, Config, Host,
363					     filename:join(TEST_SOURCE), TEST_DIR,
364					     ?TEST_FILE_DATA),
365	    create_file_on_source_node(WhichType, Config, Host,
366					     filename:join(TEST_SOURCE2), TEST_DIR,
367					     ?TEST_FILE_DATA2),
368
369	    #'CosFileTransfer_FileWrapper'{the_file = FileS} =
370		?matchnopr({'CosFileTransfer_FileWrapper', _, nfile},
371			   'CosFileTransfer_FileTransferSession':get_file(FSS, TEST_SOURCE)),
372	    #'CosFileTransfer_FileWrapper'{the_file = FileS2} =
373		?matchnopr({'CosFileTransfer_FileWrapper', _, nfile},
374			   'CosFileTransfer_FileTransferSession':get_file(FSS, TEST_SOURCE2)),
375
376	    #any{value=Count2} = ?match({any, _, _}, 'CosPropertyService_PropertySet':
377					get_property_value(Dir, "num_children")),
378	    timer:sleep(2000),
379	    ?match(true, (Count1+2 == Count2)),
380
381            %% Create a target File
382	    FileT = ?matchnopr({_,_,_},
383				     'CosFileTransfer_FileTransferSession':create_file(FST, TEST_TARGET)),
384            %% Try to delete the non-existing file.
385	    ?match({'EXCEPTION', _},
386			 'CosFileTransfer_FileTransferSession':delete(FST, FileT)),
387
388	    ?match(ok, 'CosFileTransfer_FileTransferSession':transfer(FSS, FileS, FileT)),
389
390            %% Remove this test when ftp supports append.
391	    case WhichType of
392		{'NATIVE', 'cosFileTransferNATIVE_file'} ->
393		    ?match(ok, 'CosFileTransfer_FileTransferSession':append(FSS, FileS, FileT)),
394		    ?match(ok, 'CosFileTransfer_FileTransferSession':insert(FSS, FileS2, FileT, 7));
395		_->
396		    ok
397	    end,
398
399            %% Delete source and target files
400	    ?match(ok, 'CosFileTransfer_FileTransferSession':delete(FSS, FileS)),
401	    ?match(ok, 'CosFileTransfer_FileTransferSession':delete(FSS, FileS2)),
402	    ?match(ok, 'CosFileTransfer_FileTransferSession':delete(FST, FileT)),
403
404            %% Should be back where we started.
405	    timer:sleep(2000),
406	    #any{value=Count3} = ?match({any, _, _}, 'CosPropertyService_PropertySet':
407					get_property_value(Dir, "num_children")),
408	    ?match(true, (Count1 == Count3)),
409
410
411	    ?match(false, corba_object:non_existent(FSS)),
412	    ?match(false, corba_object:non_existent(FST)),
413	    ?match(ok, 'CosFileTransfer_FileTransferSession':logout(FSS)),
414	    ?match(ok, 'CosFileTransfer_FileTransferSession':logout(FST)),
415            %% To make sure Orber can remove it from mnesia.
416	    timer:sleep(2000),
417	    ?match(true, corba_object:non_existent(FSS)),
418	    ?match(true, corba_object:non_existent(FST)),
419	    ?match(ok, remote_apply(Node, ?MODULE, uninstall_data, [Name])),
420	    stop_orber_remote(Node, normal),
421	    ok
422    end.
423
424%%-----------------------------------------------------------------
425%%  FileTransferSession API tests
426%%-----------------------------------------------------------------
427fts_ftp_dir_api(Config) ->
428    {ok, Node} = create_node("ftp_dir_api", 4009, normal),
429    dir_helper(Config, 'FTP', ?TEST_DIR, Node, 4009, "ftp_dir_api").
430
431fts_native_dir_api(Config) ->
432    {ok, Node} = create_node("native_dir_api", 4010, normal),
433    {ok, Pwd} = file:get_cwd(),
434    dir_helper(Config, {'NATIVE', 'cosFileTransferNATIVE_file'},
435	       filename:split(Pwd), Node, 4010, "native_dir_api").
436
437dir_helper(Config, WhichType, TEST_DIR, Node, Port, Name) ->
438    case ftp_host(Config) of
439	{skipped, SkippedReason} ->
440	    {skipped, SkippedReason};
441	Host ->
442	    TEST_DIR_LEVEL1 = TEST_DIR ++ [create_name(remove_me_dir1)],
443	    TEST_DIR_LEVEL2 = TEST_DIR_LEVEL1 ++ [create_name(remove_me_dir2)],
444
445	    io:format("<<<<<< CosFileTransfer Testing Configuration >>>>>>~n",[]),
446	    io:format("Top Dir: ~p~nLevel2 Dir: ~p~n", [TEST_DIR_LEVEL1, TEST_DIR_LEVEL2]),
447
448	    ?match(ok, remote_apply(Node, ?MODULE, install_data,
449					  [tcp, {WhichType, Host, Name}])),
450
451	    VFS = ?matchnopr({'IOP_IOR',"IDL:omg.org/CosFileTransfer/VirtualFileSystem:1.0",_},
452				   corba:string_to_object("corbaname::1.2@localhost:"++integer_to_list(Port)++"/NameService#"++Name)),
453
454            %% Start two File Transfer Sessions (Source and Target).
455	    {FS, DirS} = ?matchnopr({{'IOP_IOR',_,_}, _},
456					  'CosFileTransfer_VirtualFileSystem':login(VFS,
457										    ?FTP_USER,
458										    ?FTP_PASS,
459										    ?FTP_ACC)),
460
461            %% Do some basic test on one of the Directories attributes.
462	    ?match([_H|_], 'CosFileTransfer_Directory':'_get_name'(DirS)),
463	    ?match([_H|_], 'CosFileTransfer_Directory':'_get_complete_file_name'(DirS)),
464	    ?match({'IOP_IOR',[],[]}, 'CosFileTransfer_Directory':'_get_parent'(DirS)),
465	    ?matchnopr(FS, 'CosFileTransfer_Directory':'_get_associated_session'(DirS)),
466
467            %% Create a Root Directory. Currently we only need to create one but
468            %% later on, when supporting other protocols than FTP it's not enough.
469	    Dir1 =  'CosFileTransfer_FileTransferSession':create_directory(FS,
470										 TEST_DIR_LEVEL1),
471	    io:format("<<<<<< CosFileTransfer Testing Properties >>>>>>~n",[]),
472	    ?match({ok, [tk_long, tk_boolean]},
473			 'CosFileTransfer_Directory':get_allowed_property_types(Dir1)),
474	    ?match({ok, [_,_]},
475			 'CosFileTransfer_Directory':get_allowed_properties(Dir1)),
476	    ?match({'EXCEPTION', _},
477			 'CosFileTransfer_Directory':define_property_with_mode(Dir1,
478									       "num_children",
479									       #any{typecode=tk_long, value=0},
480									       fixed_readonly)),
481	    ?match({'EXCEPTION', _},
482			 'CosFileTransfer_Directory':define_property_with_mode(Dir1,
483									       "wrong",
484									       #any{typecode=tk_long, value=0},
485									       fixed_readonly)),
486	    ?match({'EXCEPTION', _},
487			 'CosFileTransfer_Directory':define_property_with_mode(Dir1,
488									       "num_children",
489									       #any{typecode=tk_short, value=0},
490									       fixed_readonly)),
491	    ?match({'EXCEPTION', _},
492			 'CosFileTransfer_Directory':define_property_with_mode(Dir1,
493									       "num_children",
494									       #any{typecode=tk_long, value=0},
495									       fixed_normal)),
496	    ?match({'EXCEPTION', _},
497			 'CosFileTransfer_Directory':define_properties_with_modes(Dir1,
498										  [#'CosPropertyService_PropertyDef'
499										   {property_name  = "num_children",
500										    property_value = #any{typecode=tk_long, value=0},
501										    property_mode  = fixed_readonly}])),
502	    ?match(fixed_readonly,
503			 'CosFileTransfer_Directory':get_property_mode(Dir1, "num_children")),
504	    ?match({true,
505			  [#'CosPropertyService_PropertyMode'{property_name = "num_children",
506							      property_mode = fixed_readonly}]},
507			 'CosFileTransfer_Directory':get_property_modes(Dir1, ["num_children"])),
508	    ?match({'EXCEPTION', _},
509			 'CosFileTransfer_Directory':set_property_mode(Dir1, "num_children", fixed_readonly)),
510
511	    ?match({'EXCEPTION', _},
512			 'CosFileTransfer_Directory':
513			 set_property_modes(Dir1,
514					    [#'CosPropertyService_PropertyMode'
515					     {property_name = "num_children",
516					      property_mode = fixed_readonly}])),
517	    ?match({'EXCEPTION', _},
518			 'CosFileTransfer_Directory':
519			 set_property_modes(Dir1,
520					    [#'CosPropertyService_PropertyMode'
521					     {property_name = "wrong",
522					      property_mode = fixed_readonly}])),
523	    ?match({'EXCEPTION', _},
524			 'CosFileTransfer_Directory':
525			 set_property_modes(Dir1,
526					    [#'CosPropertyService_PropertyMode'
527					     {property_name = "num_children",
528					      property_mode = fixed_normal}])),
529	    ?match({'EXCEPTION', _},
530			 'CosFileTransfer_Directory':define_property(Dir1,
531								     "num_children",
532								     #any{typecode=tk_long, value=0})),
533	    ?match({'EXCEPTION', _},
534			 'CosFileTransfer_Directory':define_property(Dir1,
535								     "wrong",
536								     #any{typecode=tk_long, value=0})),
537	    ?match({'EXCEPTION', _},
538			 'CosFileTransfer_Directory':define_property(Dir1,
539								     "num_children",
540								     #any{typecode=tk_short, value=0})),
541
542	    ?match({'EXCEPTION', _},
543			 'CosFileTransfer_Directory':define_property(Dir1,
544								     "num_children",
545								     #any{typecode=tk_long, value=0})),
546
547	    ?match({'EXCEPTION', _},
548			 'CosFileTransfer_Directory':
549			 define_properties(Dir1,
550					   [#'CosPropertyService_Property'
551					    {property_name = "num_children",
552					     property_value = #any{typecode=tk_long,
553								   value=0}}])),
554	    ?match({'EXCEPTION', _},
555			 'CosFileTransfer_Directory':
556			 define_properties(Dir1,
557					   [#'CosPropertyService_Property'
558					    {property_name = "wrong",
559					     property_value = #any{typecode=tk_long,
560								   value=0}}])),
561	    ?match({'EXCEPTION', _},
562			 'CosFileTransfer_Directory':
563			 define_properties(Dir1,
564					   [#'CosPropertyService_Property'
565					    {property_name = "num_children",
566					     property_value = #any{typecode=tk_short,
567								   value=0}}])),
568	    ?match(2, 'CosFileTransfer_Directory':get_number_of_properties(Dir1)),
569
570	    ?match({ok, ["num_children", "is_directory"], {'IOP_IOR',[],[]}},
571			 'CosFileTransfer_Directory':get_all_property_names(Dir1, 2)),
572	    ?match({ok, ["is_directory"], _},
573			 'CosFileTransfer_Directory':get_all_property_names(Dir1, 1)),
574
575	    ?match(#any{},
576			 'CosFileTransfer_Directory':get_property_value(Dir1, "num_children")),
577	    ?match(#any{},
578			 'CosFileTransfer_Directory':get_property_value(Dir1, "is_directory")),
579	    ?match({'EXCEPTION', _},
580			 'CosFileTransfer_Directory':get_property_value(Dir1, "wrong")),
581
582	    ?match({true,
583			  [#'CosPropertyService_Property'{property_name = "num_children"}]},
584			 'CosFileTransfer_Directory':get_properties(Dir1, ["num_children"])),
585	    ?match({false,
586			  [#'CosPropertyService_Property'{property_name = "wrong"}]},
587			 'CosFileTransfer_Directory':get_properties(Dir1, ["wrong"])),
588
589	    ?match({ok, [_],_},
590			 'CosFileTransfer_Directory':get_all_properties(Dir1, 1)),
591	    ?match({ok, [_,_], {'IOP_IOR',[],[]}},
592			 'CosFileTransfer_Directory':get_all_properties(Dir1, 2)),
593
594	    ?match({'EXCEPTION', _},
595			 'CosFileTransfer_Directory':delete_property(Dir1, "num_children")),
596	    ?match({'EXCEPTION', _},
597			 'CosFileTransfer_Directory':delete_property(Dir1, "wrong")),
598
599
600	    ?match({'EXCEPTION', _},
601			 'CosFileTransfer_Directory':delete_properties(Dir1, ["num_children"])),
602	    ?match({'EXCEPTION', _},
603			 'CosFileTransfer_Directory':delete_properties(Dir1, ["wrong"])),
604	    ?match(false, 'CosFileTransfer_Directory':delete_all_properties(Dir1)),
605	    ?match(true,
606			 'CosFileTransfer_Directory':is_property_defined(Dir1, "num_children")),
607	    ?match(false,
608			 'CosFileTransfer_Directory':is_property_defined(Dir1, "wrong")),
609
610            %% The Top Dir should be empty and ...
611	    ?match({ok,[],_}, 'CosFileTransfer_Directory':list(Dir1, 1000)),
612	    ?match( #any{value=0},
613			  'CosPropertyService_PropertySet':get_property_value(Dir1, "num_children")),
614            %% Create a sub-directory.
615	    Dir2 = 'CosFileTransfer_FileTransferSession':create_directory(FS,
616										TEST_DIR_LEVEL2),
617	    ?match( #any{value=1},
618			  'CosPropertyService_PropertySet':get_property_value(Dir1, "num_children")),
619
620	    ?match({ok, [_,_], {'IOP_IOR',[],[]}},
621			 'CosFileTransfer_Directory':get_all_properties(Dir1, 2)),
622	    {_,_,Iterator1} = ?match({ok, [_], _},
623					   'CosFileTransfer_Directory':get_all_properties(Dir1, 1)),
624	    ?match({false, [_]},
625			 'CosPropertyService_PropertiesIterator':next_n(Iterator1,4)),
626
627	    {_,_,Iterator0} = ?match({ok, [], _},
628					   'CosFileTransfer_Directory':get_all_properties(Dir1, 0)),
629
630	    ?match({false, [_, {'CosPropertyService_Property',
631				      "num_children",{any,tk_long,1}}]},
632			 'CosPropertyService_PropertiesIterator':next_n(Iterator0,4)),
633
634	    ?match({true,
635			  [#'CosPropertyService_Property'{property_name = "num_children"}]},
636			 'CosFileTransfer_Directory':get_properties(Dir1, ["num_children"])),
637
638            %% The Top Directory is not emtpy any more and ...
639	    {ok,[#'CosFileTransfer_FileWrapper'{the_file = DirRef}],_} =
640		?matchnopr({ok,[{'CosFileTransfer_FileWrapper', _, ndirectory}],_},
641			   'CosFileTransfer_Directory':list(Dir1, 1000)),
642            %% ... its name eq. to 'TEST_DIR_LEVEL2'
643	    ?match(TEST_DIR_LEVEL2,
644			 'CosFileTransfer_Directory':'_get_complete_file_name'(DirRef)),
645
646	    #'CosFileTransfer_FileWrapper'{the_file = Dir3} =
647		?matchnopr({'CosFileTransfer_FileWrapper', _, ndirectory},
648			   'CosFileTransfer_FileTransferSession':get_file(FS, TEST_DIR_LEVEL1)),
649
650            %% Must get the same result for the 'get_file' operation.
651	    {ok,[#'CosFileTransfer_FileWrapper'{the_file = DirRef2}],_} =
652		?matchnopr({ok,[{'CosFileTransfer_FileWrapper', _, ndirectory}],_},
653			   'CosFileTransfer_Directory':list(Dir3,1000)),
654	    ?match(TEST_DIR_LEVEL2,
655			 'CosFileTransfer_Directory':'_get_complete_file_name'(DirRef2)),
656
657            %% Since the top directory isn't empty deleting it must fail.
658	    ?match({'EXCEPTION', _},
659			 'CosFileTransfer_FileTransferSession':delete(FS, Dir1)),
660
661            %% Delete the sub-directory and ...
662	    ?match(ok, 'CosFileTransfer_FileTransferSession':delete(FS, Dir2)),
663            %% ... see if the top directory realyy is empty.
664	    ?match({ok,[],_}, 'CosFileTransfer_Directory':list(Dir1, 1000)),
665
666	    ?match(ok, 'CosFileTransfer_FileTransferSession':delete(FS, Dir1)),
667            %% Test if the top directory been removed as intended.
668	    ?match({'EXCEPTION', {'CosFileTransfer_FileNotFoundException', _, _}},
669			 'CosFileTransfer_FileTransferSession':get_file(FS, TEST_DIR_LEVEL1)),
670
671	    ?match(false, corba_object:non_existent(FS)),
672	    ?match(ok, 'CosFileTransfer_FileTransferSession':logout(FS)),
673            %% To make sure Orber can remove it from mnesia.
674	    timer:sleep(1000),
675	    ?match(true, corba_object:non_existent(FS)),
676	    ?match(ok, remote_apply(Node, ?MODULE, uninstall_data, [Name])),
677	    stop_orber_remote(Node, normal),
678	    ok
679    end.
680
681
682%%-----------------------------------------------------------------
683%%  Internal functions
684%%-----------------------------------------------------------------
685ftp_host(Config) ->
686    case ?config(ftp_remote_host, Config) of
687	undefined ->
688	    {skipped, "The configuration parameter 'ftp_remote_host' not defined."};
689	Host ->
690	    Host
691    end.
692
693loop_files([]) ->
694    io:format("@@@ DONE @@@~n", []);
695loop_files([#'CosFileTransfer_FileWrapper'{the_file = H}|T]) ->
696    FullName = 'CosFileTransfer_File':'_get_complete_file_name'(H),
697    Name = 'CosFileTransfer_File':'_get_name'(H),
698    io:format("FULL NAME: ~p   SHORT NAME: ~p~n", [FullName, Name]),
699    loop_files(T).
700
701
702create_file_on_source_node('FTP', _Config, Host, FileName, Path, Data) ->
703    io:format("<<<<<< CosFileTransfer Testing File >>>>>>~n",[]),
704    io:format("Host: ~p~nPath: ~p~nFile: ~p~n", [Host, Path, FileName]),
705    {ok, Pid} = ?match({ok, _}, inets:start(ftpc, [{host, Host}], stand_alone)),
706    ?match(ok, ftp:user(Pid, ?FTP_USER, ?FTP_PASS)),
707    ?match(ok, ftp:cd(Pid, Path)),
708    ?match(ok, ftp:send_bin(Pid, list_to_binary(Data), FileName)),
709    ?match(ok, inets:stop(ftpc, Pid));
710create_file_on_source_node({'NATIVE', _}, _Config, Host, FileName, Path, Data) ->
711    io:format("<<<<<< CosFileTransfer Testing File >>>>>>~n",[]),
712    io:format("Host: ~p~nPath: ~p~nFile: ~p~n", [Host, Path, FileName]),
713    ?match(ok, file:write_file(FileName, list_to_binary(Data))).
714
715create_name(Type) ->
716    Time = erlang:system_time(),
717    Unique = erlang:unique_integer([positive]),
718    lists:concat([Type, '_', Time, '_', Unique]).
719
720
721
722
723%%------------------------------------------------------------
724%% function : create_node/4
725%% Arguments: Name - the name of the new node (atom())
726%%            Port - which iiop_port (integer())
727%%            Domain - which domain.
728%%            Type - if /4 used the types defines the extra arguments
729%%                   to be used.
730%% Returns  : {ok, Node} | {error, _}
731%% Effect   : Starts a new slave-node with given (optinally)
732%%            extra arguments. If fails it retries 'Retries' times.
733%%------------------------------------------------------------
734create_node(Name, Port, normal) ->
735    Args = basic_args(Name),
736    create_node(Name, Port, 10, normal, Args, []);
737create_node(Name, {Port, _Depth}, ssl) ->
738    Dir = filename:join([code:lib_dir(ssl), "examples", "certs", "etc"]),
739    Args = basic_args(Name),
740    {ok, Node} = create_node(list_to_atom(Name), Port, 10, ssl, Args, []),
741    %% Client
742    rpc:call(Node, application, set_env, [cosFileTransfer, ssl_client_certfile,
743					  filename:join([Dir, "client", "cert.pem"])]),
744    rpc:call(Node, application, set_env, [cosFileTransfer, ssl_client_cacertfile,
745					  filename:join([Dir, "client", "cacerts.pem"])]),
746    rpc:call(Node, application, set_env, [cosFileTransfer, ssl_client_keyfile,
747					  filename:join([Dir, "client", "key.pem"])]),
748    rpc:call(Node, application, set_env, [cosFileTransfer, ssl_client_verify, 1]),
749    rpc:call(Node, application, set_env, [cosFileTransfer, ssl_client_depth, 0]),
750
751    %% Server
752    rpc:call(Node, application, set_env, [cosFileTransfer, ssl_server_certfile,
753					  filename:join([Dir, "server", "cert.pem"])]),
754    rpc:call(Node, application, set_env, [cosFileTransfer, ssl_server_cacertfile,
755					  filename:join([Dir, "server", "cacerts.pem"])]),
756    rpc:call(Node, application, set_env, [cosFileTransfer, ssl_server_keyfile,
757					  filename:join([Dir, "server", "key.pem"])]),
758    rpc:call(Node, application, set_env, [cosFileTransfer, ssl_server_verify, 1]),
759    rpc:call(Node, application, set_env, [cosFileTransfer, ssl_server_depth, 0]),
760    {ok, Node}.
761
762%create_node(Name, {Port, Depth}, ssl) ->
763%    TestLibs = filename:join(filename:dirname(code:which(?MODULE)), "ssl_data"),
764%    Args = basic_args(Name),
765%    SArgs = basic_ssl_args(TestLibs, Args),
766%    LArgs = level_based_ssl(Depth, TestLibs, SArgs),
767%    create_node(list_to_atom(Name), Port, 10, ssl, LArgs, [{sslpath, TestLibs}]).
768
769create_node(Name, Port, Retries, Type, Args, Options) ->
770    [_, Host] = ?match([_,_],string:tokens(atom_to_list(node()), [$@])),
771    case starter(Host, Name, Args) of
772	{ok, NewNode} ->
773            ?match(pong, net_adm:ping(NewNode)),
774            {ok, Cwd} = file:get_cwd(),
775            Path = code:get_path(),
776            ?match(ok, rpc:call(NewNode, file, set_cwd, [Cwd])),
777            true = rpc:call(NewNode, code, set_path, [Path]),
778	    ?match(ok, start_orber_remote(NewNode, Type, Options, Port)),
779            spawn_link(NewNode, ?MODULE, slave_sup, []),
780            rpc:multicall([node() | nodes()], global, sync, []),
781            {ok, NewNode};
782        {error, Reason} when Retries == 0->
783            {error, Reason};
784        {error, Reason} ->
785            io:format("Could not start slavenode ~p ~p retrying~n",
786                      [{Host, Name, Args}, Reason]),
787            timer:sleep(500),
788            create_node(Name, Port, Retries - 1, Type, Args, Options)
789    end.
790
791starter(Host, Name, Args) ->
792    slave:start(Host, Name, Args).
793
794slave_sup() ->
795    process_flag(trap_exit, true),
796    receive
797        {'EXIT', _, _} ->
798	    ignore
799    end.
800
801
802%%------------------------------------------------------------
803%% function : destroy_node
804%% Arguments: Node - which node to destroy.
805%%            Type - normal | ssl
806%% Returns  :
807%% Effect   :
808%%------------------------------------------------------------
809-ifdef(false).
810destroy_node(Node, Type) ->
811    stopper(Node, Type).
812
813stopper(Node, Type) ->
814    catch stop_orber_remote(Node, Type),
815    slave:stop(Node).
816-endif.
817
818%%------------------------------------------------------------
819%% function : remote_apply
820%% Arguments: N - Node, M - Module,
821%%            F - Function, A - Arguments (list)
822%% Returns  :
823%% Effect   :
824%%------------------------------------------------------------
825remote_apply(N, M,F,A) ->
826    case rpc:call(N, M, F, A) of
827	{badrpc, Reason} ->
828	    exit(Reason);
829	Other ->
830	    Other
831    end.
832
833%%------------------------------------------------------------
834%% function : stop_orber_remote
835%% Arguments: Node - which node to stop orber on.
836%%            Type - normal | ssl | light | .......
837%% Returns  : ok
838%% Effect   : Stops orber on given node and, if specified,
839%%            other applications or programs.
840%%------------------------------------------------------------
841stop_orber_remote(Node, ssl) ->
842    rpc:call(Node, ssl, stop, []),
843    rpc:call(Node, crypto, stop, []),
844    orb_rpc_blast(Node, ssl);
845stop_orber_remote(Node, Type) ->
846    orb_rpc_blast(Node, Type).
847
848orb_rpc_blast(Node, _) ->
849    rpc:call(Node, cosFileTransferApp, stop, []),
850    rpc:call(Node, cosProperty, stop, []),
851    rpc:call(Node, cosFileTransferApp, uninstall, []),
852    rpc:call(Node, cosProperty, uninstall, []),
853    rpc:call(Node, orber, jump_stop, []).
854
855%%------------------------------------------------------------
856%% function : start_orber_remote
857%% Arguments: Node - which node to start orber on.
858%%            Type - normal | ssl | light | .......
859%% Returns  : ok
860%% Effect   : Starts orber on given node and, if specified,
861%%            other applications or programs.
862%%------------------------------------------------------------
863start_orber_remote(Node, ssl, _Options, Port) ->
864    rpc:call(Node, ssl, start, []),
865    rpc:call(Node, crypto, start, []),
866    rpc:call(Node, ssl, seed, ["testing"]),
867    orb_rpc_setup(Node, ssl, Port);
868start_orber_remote(Node, Type, _, Port) ->
869    orb_rpc_setup(Node, Type, Port).
870
871orb_rpc_setup(Node, _, Port) ->
872    rpc:call(Node, orber, jump_start, [Port]),
873    rpc:call(Node, cosProperty, install, []),
874    rpc:call(Node, cosProperty, start, []),
875    rpc:call(Node, cosFileTransferApp, install, []).
876
877%%--------------- MISC FUNCTIONS -----------------------------
878basic_args(_Name) ->
879    TestLibs = filename:dirname(code:which(?MODULE)),
880    " -orber orber_debug_level 10" ++
881	" -pa " ++
882        TestLibs ++
883	" -pa " ++
884        filename:join(TestLibs, "all_SUITE_data") ++
885        " -pa " ++
886        filename:dirname(code:which(cosFileTransferApp)).
887
888-ifdef(false).
889basic_ssl_args(TestLibs, Args) ->
890%    Args ++
891%	" -cosFileTransfer ssl_client_certfile \\\"" ++
892%	filename:join(TestLibs, "ssl_client_cert.pem") ++
893%	"\\\" -cosFileTransfer ssl_server_certfile \\\""++
894%	filename:join(TestLibs, "ssl_server_cert.pem")++"\\\"".
895
896    io:format("<<<<<< SSL LIBS ~p >>>>>>~n",[TestLibs]),
897    NewArgs = Args ++
898	" -cosFileTransfer ssl_client_certfile \\\"" ++
899	filename:join(TestLibs, "ssl_client_cert.pem") ++
900	"\\\" -cosFileTransfer ssl_server_certfile \\\""++
901	filename:join(TestLibs, "ssl_server_cert.pem")++"\\\"",
902    io:format("<<<<<< SSL LIBS ARGS ~p >>>>>>~n",[NewArgs]),
903    NewArgs.
904
905level_based_ssl(1, _TestLibs, Args) ->
906    Args;
907level_based_ssl(2, _TestLibs, Args) ->
908    Args.% ++
909%	" -cosFileTransfer ssl_server_depth 2 " ++
910%	" -cosFileTransfer ssl_client_depth 2 " ++
911%	" -cosFileTransfer ssl_server_verify " ++
912%	" -cosFileTransfer ssl_client_verify " ++
913%	" -cosFileTransfer ssl_server_cacertfile " ++
914%	" -cosFileTransfer ssl_client_cacertfile " ++
915
916-endif.
917
918install_data(Protocol, {WhichType, Host, Name}) ->
919    io:format("<<<<<< Starting ~p/~p VFS at ~p/~p>>>>>>~n",
920	      [Protocol, WhichType, Host, Name]),
921    %% Create a Virtual File System.
922    VFS = ?match({_,_,_,_,_,_},
923		       cosFileTransferApp:create_VFS(WhichType, [], Host, ?FTP_PORT,
924						     [{protocol, Protocol}])),
925    NS = corba:resolve_initial_references("NameService"),
926    NC1 = lname_component:set_id(lname_component:create(), Name),
927    N = lname:insert_component(lname:create(), 1, NC1),
928    'CosNaming_NamingContext':rebind(NS, N, VFS).
929
930uninstall_data(Name) ->
931    VFS = ?match({_,_,_,_,_,_},
932		       corba:string_to_object("corbaname:rir:/NameService#"++Name)),
933    ?match(ok, corba:dispose(VFS)),
934    ok.
935
936
937
938%%------------------- EOF MODULE-----------------------------------
939