1/*
2Open Tracker License
3
4Terms and Conditions
5
6Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining a copy of
9this software and associated documentation files (the "Software"), to deal in
10the Software without restriction, including without limitation the rights to
11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12of the Software, and to permit persons to whom the Software is furnished to do
13so, subject to the following conditions:
14
15The above copyright notice and this permission notice applies to all licensees
16and shall be included in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25Except as contained in this notice, the name of Be Incorporated shall not be
26used in advertising or otherwise to promote the sale, use or other dealings in
27this Software without prior written authorization from Be Incorporated.
28
29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30of Be Incorporated in the United States and other countries. Other brand product
31names are registered trademarks or trademarks of their respective holders.
32All rights reserved.
33*/
34
35
36#if DEBUG
37
38#include "Tests.h"
39
40#include <Debug.h>
41#include <Locker.h>
42#include <Path.h>
43#include <String.h>
44#include <Window.h>
45
46
47#include "EntryIterator.h"
48#include "IconCache.h"
49#include "Model.h"
50#include "NodeWalker.h"
51#include "StopWatch.h"
52#include "Thread.h"
53
54
55const char* pathsToSearch[] = {
56//	"/boot/home/config/settings/NetPositive/Bookmarks/",
57#ifdef __HAIKU__
58	"/boot/system",
59#else
60	"/boot/beos",
61#endif
62	"/boot/apps",
63	"/boot/home",
64	0
65};
66
67
68namespace BTrackerPrivate {
69
70class IconSpewer : public SimpleThread {
71public:
72	IconSpewer(bool newCache = true);
73	~IconSpewer();
74	void SetTarget(BWindow* target)
75		{ this->target = target; }
76
77	void Quit();
78	void Run();
79
80protected:
81	void DrawSomeNew();
82	void DrawSomeOld();
83	const entry_ref* NextRef();
84private:
85	BLocker locker;
86	bool quitting;
87	BWindow* target;
88	TNodeWalker* walker;
89	CachedEntryIterator* cachingIterator;
90	int32 searchPathIndex;
91	bigtime_t cycleTime;
92	bigtime_t lastCycleLap;
93	int32 numDrawn;
94	BStopWatch watch;
95	bool newCache;
96	BPath currentPath;
97
98	entry_ref ref;
99};
100
101
102class IconTestWindow : public BWindow {
103public:
104	IconTestWindow();
105	bool QuitRequested();
106private:
107	IconSpewer iconSpewer;
108};
109
110}	// namespace BTrackerPrivate
111
112
113IconSpewer::IconSpewer(bool newCache)
114	:	quitting(false),
115		cachingIterator(0),
116		searchPathIndex(0),
117		cycleTime(0),
118		lastCycleLap(0),
119		numDrawn(0),
120		watch("", true),
121		newCache(newCache)
122{
123	walker = new TNodeWalker(pathsToSearch[searchPathIndex++]);
124	if (newCache)
125		cachingIterator = new CachedEntryIterator(walker, 40);
126}
127
128
129IconSpewer::~IconSpewer()
130{
131	delete walker;
132	delete cachingIterator;
133}
134
135
136void
137IconSpewer::Run()
138{
139	BStopWatch watch("", true);
140	for (;;) {
141		AutoLock<BLocker> lock(locker);
142
143		if (!lock || quitting)
144			break;
145
146		lock.Unlock();
147		if (newCache)
148			DrawSomeNew();
149		else
150			DrawSomeOld();
151	}
152}
153
154
155void
156IconSpewer::Quit()
157{
158	kill_thread(fScanThread);
159	fScanThread = -1;
160}
161
162
163const icon_size kIconSize = B_LARGE_ICON;
164const int32 kRowCount = 10;
165const int32 kColumnCount = 10;
166
167
168void
169IconSpewer::DrawSomeNew()
170{
171	target->Lock();
172	BView* view = target->FindView("iconView");
173	ASSERT(view);
174
175	BRect bounds(target->Bounds());
176	view->SetHighColor(Color(255, 255, 255));
177	view->FillRect(bounds);
178
179	view->SetHighColor(Color(0, 0, 0));
180	char buffer[256];
181	if (cycleTime) {
182		sprintf(buffer, "last cycle time %" B_PRId64 " ms", cycleTime/1000);
183		view->DrawString(buffer, BPoint(20, bounds.bottom - 20));
184	}
185
186	if (numDrawn) {
187		sprintf(buffer, "average draw time %" B_PRId64 " us per icon",
188			watch.ElapsedTime() / numDrawn);
189		view->DrawString(buffer, BPoint(20, bounds.bottom - 30));
190	}
191
192	sprintf(buffer, "directory: %s", currentPath.Path());
193	view->DrawString(buffer, BPoint(20, bounds.bottom - 40));
194
195	target->Unlock();
196
197	for (int32 row = 0; row < kRowCount; row++) {
198		for (int32 column = 0; column < kColumnCount; column++) {
199			BEntry entry(NextRef());
200			Model model(&entry, true);
201
202			if (!target->Lock())
203				return;
204
205			if (model.IsDirectory())
206				entry.GetPath(&currentPath);
207
208			IconCache::sIconCache->Draw(&model, view,
209				BPoint(column * (kIconSize + 2), row * (kIconSize + 2)),
210				kNormalIcon, kIconSize, true);
211			target->Unlock();
212			numDrawn++;
213		}
214	}
215}
216
217
218bool oldIconCacheInited = false;
219
220
221void
222IconSpewer::DrawSomeOld()
223{
224#if 0
225	if (!oldIconCacheInited)
226		BIconCache::InitIconCaches();
227
228	target->Lock();
229	target->SetTitle("old cache");
230	BView* view = target->FindView("iconView");
231	ASSERT(view);
232
233	BRect bounds(target->Bounds());
234	view->SetHighColor(Color(255, 255, 255));
235	view->FillRect(bounds);
236
237	view->SetHighColor(Color(0, 0, 0));
238	char buffer[256];
239	if (cycleTime) {
240		sprintf(buffer, "last cycle time %Ld ms", cycleTime/1000);
241		view->DrawString(buffer, BPoint(20, bounds.bottom - 20));
242	}
243	if (numDrawn) {
244		sprintf(buffer, "average draw time %Ld us per icon",
245			watch.ElapsedTime() / numDrawn);
246		view->DrawString(buffer, BPoint(20, bounds.bottom - 30));
247	}
248	sprintf(buffer, "directory: %s", currentPath.Path());
249	view->DrawString(buffer, BPoint(20, bounds.bottom - 40));
250
251	target->Unlock();
252
253	for (int32 row = 0; row < kRowCount; row++) {
254		for (int32 column = 0; column < kColumnCount; column++) {
255			BEntry entry(NextRef());
256			BModel model(&entry, true);
257
258			if (!target->Lock())
259				return;
260
261			if (model.IsDirectory())
262				entry.GetPath(&currentPath);
263
264			BIconCache::LockIconCache();
265			BIconCache* iconCache
266				= BIconCache::GetIconCache(&model, kIconSize);
267			iconCache->Draw(view, BPoint(column * (kIconSize + 2),
268				row * (kIconSize + 2)), B_NORMAL_ICON, kIconSize, true);
269			BIconCache::UnlockIconCache();
270
271			target->Unlock();
272			numDrawn++;
273		}
274	}
275#endif
276}
277
278
279const entry_ref*
280IconSpewer::NextRef()
281{
282	status_t result;
283	if (newCache)
284		result = cachingIterator->GetNextRef(&ref);
285	else
286		result = walker->GetNextRef(&ref);
287
288	if (result == B_OK)
289		return &ref;
290
291	delete walker;
292	if (!pathsToSearch[searchPathIndex]) {
293		bigtime_t now = watch.ElapsedTime();
294		cycleTime = now - lastCycleLap;
295		lastCycleLap = now;
296		PRINT(("**************************hit end of disk, starting over\n"));
297		searchPathIndex = 0;
298	}
299
300	walker = new TNodeWalker(pathsToSearch[searchPathIndex++]);
301	if (newCache) {
302		cachingIterator->SetTo(walker);
303		result = cachingIterator->GetNextRef(&ref);
304	} else
305		result = walker->GetNextRef(&ref);
306
307	ASSERT(result == B_OK);
308		// we don't expect and cannot deal with any problems here
309	return &ref;
310}
311
312
313//	#pragma mark -
314
315
316IconTestWindow::IconTestWindow()
317	:	BWindow(BRect(100, 100, 500, 600), "icon cache test",
318			B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, 0),
319		iconSpewer(modifiers() == 0)
320{
321	iconSpewer.SetTarget(this);
322	BView* view = new BView(Bounds(), "iconView", B_FOLLOW_ALL, B_WILL_DRAW);
323	AddChild(view);
324	iconSpewer.Go();
325}
326
327
328bool
329IconTestWindow::QuitRequested()
330{
331	iconSpewer.Quit();
332	return true;
333}
334
335
336void
337RunIconCacheTests()
338{
339	(new IconTestWindow())->Show();
340}
341
342#endif
343