Bug 545892 - Always pass WM_NCPAINT events to the default event procedure. r=bent...
[mozilla-central.git] / xpcom / tests / TestExpirationTracker.cpp
blob9b24159e3494ba6c45671fc812e94c6450cb4576
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is ExpirationTracker tests.
18 * The Initial Developer of the Original Code is Mozilla Foundation.
19 * Portions created by the Initial Developer are Copyright (C) 2007
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Robert O'Callahan <robert@ocallahan.org>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <prthread.h>
42 #include "nsExpirationTracker.h"
43 #include "nsMemory.h"
44 #include "nsAutoPtr.h"
45 #include "nsString.h"
46 #include "nsDirectoryServiceDefs.h"
47 #include "nsDirectoryServiceUtils.h"
48 #include "nsComponentManagerUtils.h"
49 #include "nsXPCOM.h"
50 #include "nsILocalFile.h"
51 #include "prinrval.h"
52 #include "nsThreadUtils.h"
54 namespace TestExpirationTracker {
56 struct Object {
57 Object() : mExpired(PR_FALSE) { Touch(); }
58 void Touch() { mLastUsed = PR_IntervalNow(); mExpired = PR_FALSE; }
60 nsExpirationState mExpiration;
61 nsExpirationState* GetExpirationState() { return &mExpiration; }
63 PRIntervalTime mLastUsed;
64 PRPackedBool mExpired;
67 static PRBool error;
68 static PRUint32 periodMS = 100;
69 static PRUint32 ops = 1000;
70 static PRUint32 iterations = 2;
71 static PRBool logging = 0;
72 static PRUint32 sleepPeriodMS = 50;
73 static PRUint32 slackMS = 20; // allow this much error
75 static void SignalError() {
76 printf("ERROR!\n");
77 error = PR_TRUE;
80 template <PRUint32 K> class Tracker : public nsExpirationTracker<Object,K> {
81 public:
82 Tracker() : nsExpirationTracker<Object,K>(periodMS) {
83 Object* obj = new Object();
84 mUniverse.AppendElement(obj);
85 LogAction(obj, "Created");
88 nsTArray<nsAutoArrayPtr<Object> > mUniverse;
90 void LogAction(Object* aObj, const char* aAction) {
91 if (logging) {
92 printf("%d %p(%d): %s\n", PR_IntervalNow(),
93 static_cast<void*>(aObj), aObj->mLastUsed, aAction);
97 void DoRandomOperation() {
98 Object* obj;
99 switch (rand() & 0x7) {
100 case 0: {
101 if (mUniverse.Length() < 50) {
102 obj = new Object();
103 mUniverse.AppendElement(obj);
104 nsExpirationTracker<Object,K>::AddObject(obj);
105 LogAction(obj, "Created and added");
107 break;
109 case 4: {
110 if (mUniverse.Length() < 50) {
111 obj = new Object();
112 mUniverse.AppendElement(obj);
113 LogAction(obj, "Created");
115 break;
117 case 1: {
118 obj = mUniverse[PRUint32(rand())%mUniverse.Length()];
119 if (obj->mExpiration.IsTracked()) {
120 nsExpirationTracker<Object,K>::RemoveObject(obj);
121 LogAction(obj, "Removed");
123 break;
125 case 2: {
126 obj = mUniverse[PRUint32(rand())%mUniverse.Length()];
127 if (!obj->mExpiration.IsTracked()) {
128 obj->Touch();
129 nsExpirationTracker<Object,K>::AddObject(obj);
130 LogAction(obj, "Added");
132 break;
134 case 3: {
135 obj = mUniverse[PRUint32(rand())%mUniverse.Length()];
136 if (obj->mExpiration.IsTracked()) {
137 obj->Touch();
138 nsExpirationTracker<Object,K>::MarkUsed(obj);
139 LogAction(obj, "Marked used");
141 break;
146 protected:
147 void NotifyExpired(Object* aObj) {
148 LogAction(aObj, "Expired");
149 PRIntervalTime now = PR_IntervalNow();
150 PRUint32 timeDiffMS = (now - aObj->mLastUsed)*1000/PR_TicksPerSecond();
151 // See the comment for NotifyExpired in nsExpirationTracker.h for these
152 // bounds
153 PRUint32 lowerBoundMS = (K-1)*periodMS - slackMS;
154 PRUint32 upperBoundMS = K*(periodMS + sleepPeriodMS) + slackMS;
155 if (logging) {
156 printf("Checking: %d-%d = %d [%d,%d]\n",
157 now, aObj->mLastUsed, timeDiffMS, lowerBoundMS, upperBoundMS);
159 if (timeDiffMS < lowerBoundMS || timeDiffMS > upperBoundMS) {
160 if (timeDiffMS < periodMS && aObj->mExpired) {
161 // This is probably OK, it probably just expired twice
162 } else {
163 SignalError();
166 aObj->Touch();
167 aObj->mExpired = PR_TRUE;
168 DoRandomOperation();
169 DoRandomOperation();
170 DoRandomOperation();
174 template <PRUint32 K> static PRBool test_random() {
175 srand(K);
176 error = PR_FALSE;
178 for (PRUint32 j = 0; j < iterations; ++j) {
179 Tracker<K> tracker;
181 PRUint32 i = 0;
182 for (i = 0; i < ops; ++i) {
183 if ((rand() & 0xF) == 0) {
184 // Simulate work that takes time
185 if (logging) {
186 printf("SLEEPING for %dms (%d)\n", sleepPeriodMS, PR_IntervalNow());
188 PR_Sleep(PR_MillisecondsToInterval(sleepPeriodMS));
189 // Process pending timer events
190 NS_ProcessPendingEvents(nsnull);
192 tracker.DoRandomOperation();
196 return !error;
199 static PRBool test_random3() { return test_random<3>(); }
200 static PRBool test_random4() { return test_random<4>(); }
201 static PRBool test_random8() { return test_random<8>(); }
203 typedef PRBool (*TestFunc)();
204 #define DECL_TEST(name) { #name, name }
206 static const struct Test {
207 const char* name;
208 TestFunc func;
209 } tests[] = {
210 DECL_TEST(test_random3),
211 DECL_TEST(test_random4),
212 DECL_TEST(test_random8),
213 { nsnull, nsnull }
218 using namespace TestExpirationTracker;
220 int main(int argc, char **argv) {
221 int count = 1;
222 if (argc > 1)
223 count = atoi(argv[1]);
225 if (NS_FAILED(NS_InitXPCOM2(nsnull, nsnull, nsnull)))
226 return -1;
228 while (count--) {
229 for (const Test* t = tests; t->name != nsnull; ++t) {
230 printf("%25s : %s\n", t->name, t->func() ? "SUCCESS" : "FAILURE");
234 NS_ShutdownXPCOM(nsnull);
235 return 0;