1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13: require_once dirname(__FILE__) . '/TestBase.php';
14:
15: class Ingo_ScriptTest extends Ingo_TestBase {
16:
17: function test_blacklist_rule_without_folder_will_discard_matching_message()
18: {
19: $runner = ScriptTester::factory('all', $this);
20:
21: $ob = new Ingo_Storage_Blacklist();
22: $ob->setBlacklist(array('spammer@example.com'));
23: $ob->setBlacklistFolder('');
24: $runner->addRule($ob);
25:
26: $runner->assertDeletesMessage('from_spammer');
27: $runner->assertKeepsMessage('not_from_spammer');
28: }
29:
30: function test_whitelist_rule_will_prevent_deletion_of_blacklisted_message()
31: {
32: $runner = ScriptTester::factory('all', $this);
33:
34: $bl = new Ingo_Storage_Blacklist();
35: $bl->setBlacklist(array('spammer@example.com'));
36: $bl->setBlacklistFolder('');
37: $runner->addRule($bl);
38:
39: $wl = new Ingo_Storage_Whitelist();
40: $wl->setWhitelist(array('spammer@example.com'));
41: $runner->addRule($wl);
42:
43: $runner->assertKeepsMessage('from_spammer');
44: $runner->assertKeepsMessage('not_from_spammer');
45: }
46:
47: function test_blacklist_rule_with_folder_will_move_matching_messages()
48: {
49: $runner = ScriptTester::factory('all', $this);
50:
51: $ob = new Ingo_Storage_Blacklist();
52: $ob->setBlacklist(array('spammer@example.com'));
53: $ob->setBlacklistFolder('Junk');
54: $runner->addRule($ob);
55:
56: $runner->assertMovesMessage('from_spammer', 'Junk');
57: }
58:
59: function test_partial_whitelist_address_should_not_match()
60: {
61: $runner = ScriptTester::factory('all', $this);
62:
63: $bl = new Ingo_Storage_Blacklist();
64: $bl->setBlacklist(array('spammer@example.com'));
65: $bl->setBlacklistFolder('');
66: $runner->addRule($bl);
67:
68: $wl = new Ingo_Storage_Whitelist();
69: $wl->setWhitelist(array('ammer@example.com'));
70: $runner->addRule($wl);
71:
72: $runner->assertDeletesMessage('from_spammer');
73: }
74:
75: function test_partial_blacklist_address_should_not_match()
76: {
77: $runner = ScriptTester::factory('all', $this);
78:
79: $bl = new Ingo_Storage_Blacklist();
80: $bl->setBlacklist(array('ammer@example.com'));
81: $bl->setBlacklistFolder('');
82: $runner->addRule($bl);
83:
84: $runner->assertKeepsMessage('from_spammer');
85: }
86:
87: }
88:
89: 90: 91:
92: class ScriptTester {
93:
94: var $test;
95: var $rules = array();
96:
97: function ScriptTester($test)
98: {
99: $this->test = $test;
100: }
101:
102: function addRule($rule)
103: {
104: $this->rules[] = $rule;
105: }
106:
107: function assertDeletesMessage($fixture)
108: {
109: return PEAR::raiseError('Not implemented.');
110: }
111:
112: function assertKeepsMessage($fixture)
113: {
114: return PEAR::raiseError('Not implemented.');
115: }
116:
117: function assertMovesMessage($fixture, $to_folder)
118: {
119: return PEAR::raiseError('Not implemented.');
120: }
121:
122: static function factory($type, $test)
123: {
124: $class = 'ScriptTester_' . $type;
125: $ob = new $class($test);
126: return $ob;
127: }
128:
129: function _setupStorage()
130: {
131: $GLOBALS['session']->set('ingo', 'change', 0);
132: $GLOBALS['ingo_storage'] = Ingo_Storage::factory('mock', array());
133: foreach ($this->rules as $ob) {
134: $GLOBALS['ingo_storage']->store($ob);
135: }
136: }
137:
138: }
139:
140: 141: 142:
143: class ScriptTester_imap extends ScriptTester {
144:
145: var $imap;
146: var $api;
147:
148: function _setup()
149: {
150: $this->_setupStorage();
151: $this->api = Ingo_Script_Imap_Api::factory('mock', array());
152: $this->api->loadFixtures(dirname(__FILE__) . '/_data/');
153:
154: $GLOBALS['notification'] = new Ingo_Test_Notification;
155:
156: $params = array('api' => $this->api,
157: 'spam_compare' => 'string',
158: 'spam_header' => 'X-Spam-Level',
159: 'spam_char' => '*');
160: $this->imap = Ingo_Script::factory('imap', $params);
161: }
162:
163: function _run()
164: {
165: $params = array('api' => $this->api, 'filter_seen' => 0, 'show_filter_msg' => 1);
166: $this->imap->perform($params);
167: }
168:
169: function assertDeletesMessage($fixture)
170: {
171: $this->_setup();
172: $this->test->assertTrue($this->api->hasMessage($fixture));
173: $this->_run();
174: $this->test->assertFalse($this->api->hasMessage($fixture));
175: }
176:
177: function assertKeepsMessage($fixture)
178: {
179: $this->_setup();
180: $this->test->assertTrue($this->api->hasMessage($fixture));
181: $this->_run();
182: $this->test->assertTrue($this->api->hasMessage($fixture));
183: }
184:
185: function assertMovesMessage($fixture, $to_folder)
186: {
187: $this->_setup();
188: $this->test->assertTrue($this->api->hasMessage($fixture));
189: $this->_run();
190: $this->test->assertFalse($this->api->hasMessage($fixture));
191: $this->test->assertTrue($this->api->hasMessage($fixture, $to_folder));
192: }
193:
194: }
195:
196: 197: 198: 199:
200: class ScriptTester_all extends ScriptTester {
201:
202:
203: var $backends = array('sieve');
204:
205: function _delegate($method, $params)
206: {
207: foreach ($this->backends as $backend) {
208: $runner = ScriptTester::factory($backend, $this->test);
209: foreach ($this->rules as $rule) {
210: $runner->addRule($rule);
211: }
212: call_user_func_array(array($runner, $method), $params);
213: }
214: }
215:
216: function assertDeletesMessage($fixture)
217: {
218: $this->_delegate('assertDeletesMessage', array($fixture));
219: }
220:
221: function assertKeepsMessage($fixture)
222: {
223: $this->_delegate('assertKeepsMessage', array($fixture));
224: }
225:
226: function assertMovesMessage($fixture, $to_folder)
227: {
228: $this->_delegate('assertMovesMessage', array($fixture, $to_folder));
229: }
230:
231: }
232:
233: 234: 235: 236:
237: class ScriptTester_sieve extends ScriptTester {
238:
239: function assertDeletesMessage($fixture)
240: {
241: $this->_run();
242: $this->_assertOutput("DISCARD on msg uid " . $this->uids[$fixture]);
243: }
244:
245: function assertKeepsMessage($fixture)
246: {
247: $this->_run();
248: $this->_assertOutput("KEEP on msg uid " . $this->uids[$fixture]);
249: }
250:
251: function assertMovesMessage($fixture, $to_folder)
252: {
253: $this->_run();
254: $this->_assertOutput("FILEINTO on msg uid " . $this->uids[$fixture] .
255: ": delivering into " . $to_folder);
256: }
257:
258: function _assertOutput($want)
259: {
260: $this->test->assertRegExp('/' . preg_quote($want, '/') . '/',
261: $this->output,
262: "FAILED SIEVE SCRIPT:\n\n", $this->sieve_text, "\n\n");
263: }
264:
265: var $mbox;
266: var $sieve;
267: var $script_text;
268: var $output;
269: var $uids;
270:
271: function _run()
272: {
273: $this->_buildMailboxFile();
274: $this->_writeSieveScript();
275: $this->_runSieve();
276:
277: @unlink($this->mbox);
278: @unlink($this->sieve);
279: }
280:
281: function _buildMailboxFile()
282: {
283: $this->uids = array();
284: $this->mbox = tempnam('/tmp', 'mbox');
285: $mh = fopen($this->mbox, 'w');
286: $uid = 1;
287:
288: $dh = opendir(dirname(__FILE__) . '/_data');
289: while (($dent = readdir($dh)) !== false) {
290: if ($dent == '.' || $dent == '..' || $dent == 'CVS') {
291: continue;
292: }
293: $filespec = dirname(__FILE__) . '/_data/' . $dent;
294: $fh = fopen($filespec, 'r');
295: $data = fread($fh, filesize($filespec));
296: fclose($fh);
297:
298: fwrite($mh, $data);
299: if ($data{strlen($data)-1} != "\n") {
300: fwrite($mh, "\n");
301: }
302:
303: $this->uids[$dent] = $uid++;
304: }
305: closedir($dh);
306:
307: fclose($mh);
308: }
309:
310: function _writeSieveScript()
311: {
312: $params = array('date_format' => '%x',
313: 'time_format' => '%R',
314: 'spam_compare' => 'string',
315: 'spam_header' => 'X-Spam-Level',
316: 'spam_char' => '*');
317:
318: $this->_setupStorage();
319: $script = Ingo_Script::factory('sieve', $params);
320:
321: $this->sieve = tempnam('/tmp', 'sieve');
322: $fh = fopen($this->sieve, 'w');
323:
324: $this->sieve_text = $script->generate();
325: fwrite($fh, $this->sieve_text);
326: fclose($fh);
327: }
328:
329: function _runSieve()
330: {
331: $this->output = '';
332: $ph = popen("sieve -vv -n -f " . escapeshellarg($this->mbox) . " " .
333: escapeshellarg($this->sieve) . ' 2>&1', 'r');
334: while (!feof($ph)) {
335: $data = fread($ph, 512);
336: if (is_string($data)) {
337: $this->output .= $data;
338: }
339: }
340: pclose($ph);
341: }
342:
343: }
344:
345: