1<?php
2
3/**
4 * General tests for the log404 plugin
5 *
6 * @group plugin_log404
7 * @group plugins
8 */
9class general_plugin_log404_test extends DokuWikiTest {
10
11    protected $pluginsEnabled = array('log404');
12
13    /**
14     * Simple test to make sure the plugin.info.txt is in correct format
15     */
16    public function test_plugininfo() {
17        $file = __DIR__.'/../plugin.info.txt';
18        $this->assertFileExists($file);
19        $info = confToHash($file);
20
21        $this->assertArrayHasKey('base', $info);
22        $this->assertArrayHasKey('author', $info);
23        $this->assertArrayHasKey('email', $info);
24        $this->assertArrayHasKey('date', $info);
25        $this->assertArrayHasKey('name', $info);
26        $this->assertArrayHasKey('desc', $info);
27        $this->assertArrayHasKey('url', $info);
28
29        $this->assertEquals('log404', $info['base']);
30        $this->assertRegExp('/^https?:\/\//', $info['url']);
31        $this->assertTrue(mail_isvalid($info['email']));
32        $this->assertRegExp('/^\d\d\d\d-\d\d-\d\d$/', $info['date']);
33        $this->assertTrue(false !== strtotime($info['date']));
34    }
35
36    /**
37     * Test that the CSV is created and the appropriate record is written to it.
38     */
39    public function test_csv() {
40        $log = plugin_load('helper', 'log404');
41
42        // Make sure there's nothing there to start with
43        $this->assertEquals(0, $log->recordCount());
44
45        // Execute a GET request
46        $request1 = new TestRequest();
47        $request1->setServer('REMOTE_ADDR', '192.0.2.45'); // c.f. RFC 5737
48        $request1->setServer('HTTP_USER_AGENT', 'An agent');
49        $request1->get(array('id' => 'page-that-does-not-exist'));
50
51        // Now there should be one record.
52        $log->load();
53        $this->assertFileExists($log->filename(), "File exists");
54        $this->assertEquals(1, $log->recordCount());
55        // Which should have one hit, from 'An agent'
56        $record1 = $log->getRecord('page-that-does-not-exist');
57        $this->assertEquals(1, $record1['count']);
58        $this->assertEquals('An agent', $record1['hits'][0]['user_agent']);
59        $this->assertEquals('192.0.2.45', $record1['hits'][0]['ip']);
60
61        // Hit the same file again, and increment the count
62        $request2 = new TestRequest();
63        $request2->setServer('HTTP_USER_AGENT', 'An agent');
64        $request2->get(array('id' => 'page-that-does-not-exist'));
65        $log->load();
66        $record2 = $log->getRecord('page-that-does-not-exist');
67        $this->assertEquals(2, $record2['count']);
68    }
69
70    /**
71     * Test that log records are ordered by hit count.
72     */
73    public function test_ordering() {
74        $log = plugin_load('helper', 'log404');
75        // Reset the log
76        @unlink($log->filename());
77
78        // Hit page A twice, then page B once, and page A will be first
79        $request1 = new TestRequest();
80        $request1->get(array('id' => 'a'));
81        $request2 = new TestRequest();
82        $request2->get(array('id' => 'a'));
83        $request3 = new TestRequest();
84        $request3->get(array('id' => 'b'));
85        $log->load();
86        $firstRecord = array_keys($log->getRecords());
87        $this->assertEquals('a', array_shift($firstRecord));
88
89        // Then add two more for B, and it should now be first
90        $request4 = new TestRequest();
91        $request4->get(array('id' => 'b'));
92        $request5 = new TestRequest();
93        $request5->get(array('id' => 'b'));
94        $log->load();
95        $newFirstRecord = array_keys($log->getRecords());
96        $this->assertEquals('b', array_shift($newFirstRecord));
97    }
98
99    /**
100     * Test that we can delete log entries, based on their page ID.
101     */
102    public function test_delete() {
103        $log = plugin_load('helper', 'log404');
104        // Reset the log
105        @unlink($log->filename());
106        // Create two requests for page A, then one for B
107        $request1 = new TestRequest();
108        $request1->get(array('id' => 'a'));
109        $request2 = new TestRequest();
110        $request2->get(array('id' => 'a'));
111        $request3 = new TestRequest();
112        $request3->get(array('id' => 'b'));
113        // Then delete page A from the log
114        $log->deleteRecord('a');
115        // And check that it's not there, and that B is
116        $this->assertFalse($log->getRecord('a'));
117        $b = $log->getRecord('b');
118        $this->assertEquals(1, $b['count']);
119    }
120
121    /**
122     * Test that when deleting, multiple hits of non-deleted pages do remain.
123     */
124    public function test_delete_hits() {
125        $log = plugin_load('helper', 'log404');
126        // Reset the log
127        @unlink($log->filename());
128        // Create two requests for page A, then one for B, one for A, one for B.
129        $request1 = new TestRequest();
130        $request1->get(array('id' => 'a'));
131        $request2 = new TestRequest();
132        $request2->get(array('id' => 'a'));
133        $request3 = new TestRequest();
134        $request3->get(array('id' => 'b'));
135        $request4 = new TestRequest();
136        $request4->get(array('id' => 'a'));
137        $request5 = new TestRequest();
138        $request5->get(array('id' => 'b'));
139        // Then delete page B from the log
140        $log->deleteRecord('b');
141        // And check that it's not there, and that A still has 3 hits
142        $this->assertFalse($log->getRecord('b'));
143        $a = $log->getRecord('a');
144        $this->assertEquals(3, $a['count']);
145    }
146
147    /**
148     * Test that deleting a record doesn't break other data in the log
149     */
150    public function test_delete_leaves_data() {
151        $log = plugin_load('helper', 'log404');
152        // Reset the log
153        @unlink($log->filename());
154
155        // Request a page, providing data
156        $request1 = new TestRequest();
157        $request1->setServer('REMOTE_ADDR', '192.0.2.45'); // c.f. RFC 5737
158        $request1->setServer('HTTP_REFERER', 'Wherefrom');
159        $request1->setServer('HTTP_USER_AGENT', 'An agent');
160        $request1->get(array('id' => 'page-that-does-not-exist'));
161        // Request and then delete another page
162        $request2 = new TestRequest();
163        $request2->get(array('id' => 'a'));
164        $log->deleteRecord('a');
165
166        // Check that our data remains
167        $log->load();
168        $a = $log->getRecord('page-that-does-not-exist');
169        $this->assertEquals('192.0.2.45', $a['hits'][0]['ip']);
170        $this->assertEquals('Wherefrom', $a['hits'][0]['referer']);
171        $this->assertEquals('An agent', $a['hits'][0]['user_agent']);
172    }
173
174    /**
175     * Test that, if provided, an IP address is logged.
176     * @link https://github.com/samwilson/dokuwiki-plugin-log404/issues/1
177     */
178    public function test_ip_address() {
179        $log = plugin_load('helper', 'log404');
180        // Reset the log
181        @unlink($log->filename());
182
183        // Request a page.
184        $request1 = new TestRequest();
185        //$request1->setServer('HTTP_USER_AGENT', '198.51.100.35');
186        $request1->get(array('id' => 'page-that-does-not-exist'));
187
188        // Check the log. This IP is set in _test/bootstrap.php
189        $log->load();
190        $a = $log->getRecord('page-that-does-not-exist');
191        $this->assertEquals('87.142.120.6', $a['hits'][0]['ip']);
192    }
193
194}
195