12 #include <TestShell.h>
13 #include <TestUtils.h>
14 #include <cppunit/TestAssert.h>
16 #include "AppRunner.h"
18 static const char *kAppRunnerTeamPort
= "app runner team port";
21 AppRunner::AppRunner(bool requestQuitOnDestruction
)
29 fRequestQuitOnDestruction(requestQuitOnDestruction
)
34 AppRunner::~AppRunner()
36 if (fRequestQuitOnDestruction
)
40 wait_for_thread(fReader
, &result
);
46 AppRunner::Run(const char *command
, const char *args
, bool findCommand
)
48 status_t error
= (HasQuitted() ? B_OK
: B_ERROR
);
52 find_test_app(command
, &appPath
);
53 command
= appPath
.String();
55 get_ref_for_path(command
, &fRef
);
56 // add args, i.e. compose the command line
57 BString
cmdLine(command
);
63 bool teamPortLocked
= false;
65 teamPortLocked
= _LockTeamPort();
72 if (system(cmdLine
.String()) != 0)
77 fRemotePort
= _ReadPortID(fMessenger
);
81 // unlock the team port
87 error
= get_port_info(fRemotePort
, &info
);
90 // spawn the reader thread
92 fReader
= spawn_thread(&_ReaderEntry
, "AppRunner reader",
93 B_NORMAL_PRIORITY
, (void*)this);
95 error
= resume_thread(fReader
);
102 kill_thread(fReader
);
111 AppRunner::HasQuitted()
114 return (get_port_info(fRemotePort
, &info
) != B_OK
);
119 AppRunner::WaitFor(bool requestQuit
)
121 if (!HasQuitted() && requestQuit
)
123 while (!HasQuitted())
136 AppRunner::AppLooperPort()
138 struct messenger_hack
{
144 bool fPreferredTarget
;
149 return ((messenger_hack
*)&fMessenger
)->fPort
;
154 AppRunner::GetRef(entry_ref
*ref
)
156 status_t error
= (ref
? B_OK
: B_ERROR
);
164 AppRunner::RequestQuit()
166 status_t error
= B_OK
;
168 BMessenger
messenger(fMessenger
);
169 error
= messenger
.SendMessage(B_QUIT_REQUESTED
);
177 AppRunner::GetOutput(BString
*buffer
)
179 status_t error
= (buffer
? B_OK
: B_BAD_VALUE
);
181 BAutolock
locker(fOutputLock
);
182 size_t size
= fOutput
.BufferLength();
183 const void *output
= fOutput
.Buffer();
185 buffer
->SetTo((const char*)output
, size
);
194 AppRunner::ReadOutput(void *buffer
, size_t size
)
196 BAutolock
locker(fOutputLock
);
197 return fOutput
.Read(buffer
, size
);
202 AppRunner::ReadOutputAt(off_t position
, void *buffer
, size_t size
)
204 BAutolock
locker(fOutputLock
);
205 return fOutput
.ReadAt(position
, buffer
, size
);
210 AppRunner::_ReaderEntry(void *data
)
213 if (AppRunner
*me
= (AppRunner
*)data
)
214 result
= me
->_ReaderLoop();
220 AppRunner::_ReaderLoop()
223 port_id port
= fRemotePort
;
224 status_t error
= B_OK
;
225 while (error
== B_OK
) {
227 ssize_t bytes
= read_port(port
, &code
, buffer
, sizeof(buffer
) - 1);
230 BAutolock
locker(fOutputLock
);
231 off_t oldPosition
= fOutput
.Seek(0, SEEK_END
);
232 fOutput
.Write(buffer
, bytes
);
233 fOutput
.Seek(oldPosition
, SEEK_SET
);
234 } else if (bytes
< 0)
243 AppRunner::_LockTeamPort()
245 bool result
= fTeamPortLock
.Lock();
246 // lazy port creation
247 if (result
&& fTeamPort
< 0) {
248 fTeamPort
= create_port(5, kAppRunnerTeamPort
);
250 fTeamPortLock
.Unlock();
259 AppRunner::_UnlockTeamPort()
261 fTeamPortLock
.Unlock();
266 AppRunner::_ReadPortID(BMessenger
&messenger
)
269 ssize_t size
= read_port(fTeamPort
, &port
, &messenger
, sizeof(BMessenger
));
277 port_id
AppRunner::fTeamPort
= -1;
280 BLocker
AppRunner::fTeamPortLock
;
285 find_test_app(const char *testApp
, BString
*path
)
287 status_t error
= (testApp
&& path
? B_OK
: B_BAD_VALUE
);
289 *path
= BTestShell::GlobalTestDir();
290 path
->CharacterEscape(" \t\n!\"'`$&()?*+{}[]<>|", '\\');
302 find_test_app(const char *testApp
, entry_ref
*ref
)
304 status_t error
= (testApp
&& ref
? B_OK
: B_BAD_VALUE
);
307 error
= find_test_app(testApp
, &path
);
309 error
= get_ref_for_path(path
.String(), ref
);