Overview

Packages

  • Horde
    • Icalendar
      • UnitTests
  • Ingo
    • UnitTests
  • None

Classes

  • Ingo_Application
  • Ingo_Block_Overview
  • Ingo_Script_Imap_Mock
  • Ingo_Test_Notification
  • ScriptTester
  • ScriptTester_all
  • ScriptTester_imap
  • ScriptTester_sieve
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Test cases for Ingo_Script:: and derived classes
  4:  *
  5:  * See the enclosed file LICENSE for license information (ASL).  If you
  6:  * did not receive this file, see http://www.horde.org/licenses/apache.
  7:  *
  8:  * @author     Jason M. Felice <jason.m.felice@gmail.com>
  9:  * @package    Ingo
 10:  * @subpackage UnitTests
 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:  * Abstract base class for strategies for testing different Script backends
 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:  * Implementation of ScriptTester:: for testing 'imap' scripts
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:  * This script tester iterates through all enabled backends to verify that
198:  * each one works properly.
199:  */
200: class ScriptTester_all extends ScriptTester {
201: 
202:     // No imap tests for now, until the mock searching works again.
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:  * Test the sieve Script backend.  This uses the command-line `sieve' from
235:  * the GNU mailutils package.
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: 
API documentation generated by ApiGen