1 /*******************************************************************************
2 
3     Test for the SignalExt behaviour.
4 
5     copyright: Copyright (c) 2015 dunnhumby Germany GmbH. All rights reserved
6 
7 *******************************************************************************/
8 
9 module integrationtest.signalext.main;
10 
11 import ocean.transition;
12 
13 import core.sys.posix.signal;
14 import ocean.core.Test;
15 import ocean.sys.ErrnoException;
16 import ocean.util.app.DaemonApp;
17 import ocean.io.select.client.TimerEvent;
18 
19 /// Counters incremented from original and application's
20 /// signal handler
21 private int main_counter;
22 private int app_counter;
23 
24 class MyApp : DaemonApp
25 {
26     import ocean.io.select.EpollSelectDispatcher;
27 
28     private EpollSelectDispatcher epoll;
29 
30     this ( )
31     {
32         this.epoll = new EpollSelectDispatcher;
33 
34         istring name = "Application";
35         istring desc = "Testing signal handling.";
36 
37         DaemonApp.OptionalSettings settings;
38         settings.signals = [SIGRTMIN];
39 
40         super(name, desc, VersionInfo.init, settings);
41     }
42 
43     // Called after arguments and config file parsing.
44     override protected int run ( Arguments args, ConfigParser config )
45     {
46         this.startEventHandling(this.epoll);
47 
48         auto timer = new TimerEvent(
49                 {
50                     // This should now trigger the new handler
51                     raise(SIGRTMIN);
52                     return false;
53                 });
54 
55         timer.set(0, 100, 0, 0);
56         this.epoll.register(timer);
57 
58         this.epoll.eventLoop();
59         return 0; // return code to OS
60     }
61 
62     // Handle those signals we were interested in
63     override public void onSignal ( int signal )
64     {
65         test!("==")(signal, SIGRTMIN);
66         .app_counter++;
67         this.epoll.shutdown();
68     }
69 }
70 
71 import ocean.io.device.File;
72 import Path = ocean.io.Path;
73 import ocean.text.util.StringC;
74 import core.sys.posix.unistd;
75 import ocean.stdc.posix.stdlib : mkdtemp;
76 
77 version(UnitTest) {} else
78 void main(istring[] args)
79 {
80     static extern(C) void sighandler (int sig)
81     {
82         main_counter++;
83     }
84 
85     // Exception to throw on failure. Instantiated for ergonomics
86     auto e = new ErrnoException;
87 
88     // Set the initial signal handler
89     sigaction_t handler, old_handler;
90     handler.sa_handler = &sighandler;
91 
92     auto sigaction_res =
93         e.enforceRetCode!(sigaction).call(SIGRTMIN, &handler, &old_handler);
94 
95     scope (exit)
96     {
97         // Restore the old one on exit
98         sigaction(SIGRTMIN, &old_handler, null);
99     }
100 
101     // The main-function signal handler should be triggered here
102     raise(SIGRTMIN);
103 
104     // Prepare environment
105     char[4096] old_cwd;
106     e.enforceRetPtr!(getcwd).call(old_cwd.ptr, old_cwd.length);
107 
108     auto tmp_path = e.enforceRetPtr!(mkdtemp)
109         .call("/tmp/Dunittest-XXXXXX\0".dup.ptr);
110 
111     scope (exit)
112     {
113         auto d_tmp_path = StringC.toDString(tmp_path);
114         // Remove all subdirectories and files in the tmp dir
115         Path.remove(Path.collate(d_tmp_path, "*", true));
116         // Remove the tmp dir itself
117         Path.remove(d_tmp_path);
118     }
119 
120     e.enforceRetCode!(chdir).call(tmp_path);
121 
122     scope (exit)
123     {
124         e.enforceRetCode!(chdir).call(old_cwd.ptr);
125     }
126 
127     // Now start the application:
128 
129     // setup directory structure needed to run
130     if (!Path.exists("etc"))
131     {
132         Path.createFolder("etc");
133     }
134 
135     if (!Path.exists("log"))
136     {
137         Path.createFolder("log");
138     }
139 
140     auto file = new File("etc/config.ini", File.ReadWriteCreate);
141 
142     file.write("[LOG.Root]\n" ~
143                "console = false\n");
144 
145     file.close();
146 
147     auto app = new MyApp;
148     auto ret = app.main(args);
149 
150     // The old handler should be triggered here
151     raise(SIGRTMIN);
152 
153     test!("==")(main_counter, 2);
154     test!("==")(app_counter, 1);
155 }