xref: /haiku/src/tests/servers/registrar/message_deliverer_test.cpp (revision bc3955fea5b07e2e94a27fc05e4bb58fe6f0319b)
1 /*
2  * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 // Small app for testing the registrar's MessageDeliverer.
7 
8 #include <errno.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 
14 #include <Application.h>
15 #include <Clipboard.h>
16 #include <Locker.h>
17 #include <Message.h>
18 #include <MessageRunner.h>
19 #include <OS.h>
20 #include <Path.h>
21 #include <Roster.h>
22 #include <String.h>
23 
24 // message what codes
25 enum {
26 	MSG_FILL_PORT	= 'fill',
27 	MSG_RUNNER		= 'runn',
28 	MSG_BROADCAST	= 'brod',
29 };
30 
31 static const uint32 sExpectedMessages[3] = {
32 	B_CLIPBOARD_CHANGED,
33 	MSG_RUNNER,
34 	MSG_BROADCAST,
35 };
36 static const int32 sExpectedMessageCount = 3;
37 static int32 sExpectedMessageIndex = 0;
38 
39 // check_expected_message
40 static
41 bool
42 check_expected_message(uint32 what)
43 {
44 	if (sExpectedMessageIndex >= sExpectedMessageCount) {
45 		printf("Unexpected message '%.4s'\n", (char*)&what);
46 		exit(1);
47 	}
48 
49 	uint32 expected = sExpectedMessages[sExpectedMessageIndex++];
50 	if (what != expected) {
51 		printf("Unexpected message '%.4s', expected was: '%.4s'\n",
52 			(char*)&what, (char*)&expected);
53 		exit(1);
54 	}
55 
56 	return (sExpectedMessageIndex == sExpectedMessageCount);
57 }
58 
59 
60 // TestApp
61 class TestApp : public BApplication {
62 public:
63 	TestApp()
64 		: BApplication("application/x-vnd.haiku.message-deliverer-test")
65 	{
66 	}
67 
68 	virtual void MessageReceived(BMessage *message)
69 	{
70 		switch (message->what) {
71 			case MSG_FILL_PORT:
72 				return;
73 			case MSG_RUNNER:
74 				printf("MSG_RUNNER\n");
75 				break;
76 			case B_CLIPBOARD_CHANGED:
77 				printf("B_CLIPBOARD_CHANGED\n");
78 				break;
79 			case MSG_BROADCAST:
80 				printf("MSG_BROADCAST\n");
81 				break;
82 			default:
83 				BApplication::MessageReceived(message);
84 				return;
85 		}
86 
87 		if (check_expected_message(message->what))
88 			PostMessage(B_QUIT_REQUESTED);
89 	}
90 };
91 
92 // main
93 int
94 main(int argc, const char *const *argv)
95 {
96 	// if started with parameter "broadcast", we broadcast a message and exit
97 	if (argc > 1 && strcmp(argv[1], "broadcast") == 0) {
98 		BMessage message(MSG_BROADCAST);
99 		status_t error = be_roster->Broadcast(&message);
100 		if (error != B_OK) {
101 			printf("Broadcast failed: %s\n", strerror(error));
102 			exit(1);
103 		}
104 		exit(0);
105 	}
106 
107 	TestApp app;
108 
109 	// fill the looper port
110 	status_t error;
111 	do {
112 		BMessage message(MSG_FILL_PORT);
113 		error = be_app_messenger.SendMessage(&message, (BHandler*)NULL, 0LL);
114 	} while (error == B_OK);
115 
116 	if (error != B_WOULD_BLOCK) {
117 		printf("sending fill message didn't fail with B_WOULD_BLOCK: %s\n",
118 			strerror(error));
119 		exit(1);
120 	}
121 
122 	// register looper for clipboard events
123 	BClipboard clipboard("message deliverer test");
124 	error = clipboard.StartWatching(be_app_messenger);
125 	if (error != B_OK) {
126 		printf("Failed to start clipboard watching: %s\n", strerror(error));
127 		exit(1);
128 	}
129 
130 	// generate a clipboard changed modification
131 	if (!clipboard.Lock()) {
132 		printf("Failed to lock clipboard.\n");
133 		exit(1);
134 	}
135 	clipboard.Clear();
136 	clipboard.Data()->AddString("test", "test data");
137 	error = clipboard.Commit();
138 	if (error != B_OK) {
139 		printf("Failed to commit clipboard data: %s\n", strerror(error));
140 		exit(1);
141 	}
142 	clipboard.Unlock();
143 
144 	// create a message runner
145 	BMessage message(MSG_RUNNER);
146 	bigtime_t interval = 100000LL;
147 	BMessageRunner runner(be_app_messenger, &message, interval, 3);
148 	error = runner.InitCheck();
149 	if (error != B_OK) {
150 		printf("Message runner initialization failed: %s\n", strerror(error));
151 		exit(1);
152 	}
153 	snooze(5 * interval);
154 
155 	// broadcast a message: We do that be starting another instance of this
156 	// app with parameter "broadcast". We can't do the broadcast ourselves,
157 	// since the message is sent only to the other applications.
158 
159 	// get our app info
160 	app_info appInfo;
161 	error = app.GetAppInfo(&appInfo);
162 	if (error != B_OK) {
163 		printf("GetAppInfo() failed: %s\n", strerror(error));
164 		exit(1);
165 	}
166 
167 	// get the app path
168 	BPath path;
169 	error = path.SetTo(&appInfo.ref);
170 	if (error != B_OK) {
171 		printf("Failed to get app path: %s\n", strerror(error));
172 		exit(1);
173 	}
174 
175 	// launch...
176 	BString commandLine(path.Path());
177 	commandLine << " broadcast";
178 	if (system(commandLine.String()) < 0) {
179 		printf("Failed re-launch app for broadcasting: %s\n", strerror(errno));
180 		exit(1);
181 	}
182 
183 	// wait a bit...
184 	snooze(100000);
185 
186 	// now start the message processing loop
187 	app.Run();
188 
189 	return 0;
190 }
191