First go at refactoring the API mechanisms
[dokuwiki.git] / _test / tests / inc / remote.test.php
blob39d3c62a1a4bfba9d65c35a725e45582735530ac
1 <?php
3 use dokuwiki\test\mock\AuthPlugin;
4 use dokuwiki\Extension\RemotePlugin;
5 use dokuwiki\Remote\Api;
6 use dokuwiki\Remote\RemoteException;
8 class RemoteAPICoreTest {
10 function getRemoteInfo() {
11 return array(
12 'wiki.stringTestMethod' => array(
13 'args' => array(),
14 'return' => 'string',
15 'doc' => 'Test method',
16 'name' => 'stringTestMethod',
17 ), 'wiki.intTestMethod' => array(
18 'args' => array(),
19 'return' => 'int',
20 'doc' => 'Test method',
21 'name' => 'intTestMethod',
22 ), 'wiki.floatTestMethod' => array(
23 'args' => array(),
24 'return' => 'float',
25 'doc' => 'Test method',
26 'name' => 'floatTestMethod',
27 ), 'wiki.dateTestMethod' => array(
28 'args' => array(),
29 'return' => 'date',
30 'doc' => 'Test method',
31 'name' => 'dateTestMethod',
32 ), 'wiki.fileTestMethod' => array(
33 'args' => array(),
34 'return' => 'file',
35 'doc' => 'Test method',
36 'name' => 'fileTestMethod',
37 ), 'wiki.voidTestMethod' => array(
38 'args' => array(),
39 'return' => 'void',
40 'doc' => 'Test method',
41 'name' => 'voidTestMethod',
42 ), 'wiki.oneStringArgMethod' => array(
43 'args' => array('string'),
44 'return' => 'string',
45 'doc' => 'Test method',
46 'name' => 'oneStringArgMethod',
47 ), 'wiki.twoArgMethod' => array(
48 'args' => array('string', 'int'),
49 'return' => 'array',
50 'doc' => 'Test method',
51 'name' => 'twoArgMethod',
52 ), 'wiki.twoArgWithDefaultArg' => array(
53 'args' => array('string', 'string'),
54 'return' => 'string',
55 'doc' => 'Test method',
56 'name' => 'twoArgWithDefaultArg',
57 ), 'wiki.publicCall' => array(
58 'args' => array(),
59 'return' => 'boolean',
60 'doc' => 'testing for public access',
61 'name' => 'publicCall',
62 'public' => 1
66 function stringTestMethod() { return 'success'; }
67 function intTestMethod() { return 42; }
68 function floatTestMethod() { return 3.14159265; }
69 function dateTestMethod() { return 2623452346; }
70 function fileTestMethod() { return 'file content'; }
71 function voidTestMethod() { return null; }
72 function oneStringArgMethod($arg) {return $arg; }
73 function twoArgMethod($string, $int) { return array($string, $int); }
74 function twoArgWithDefaultArg($string1, $string2 = 'default') { return array($string1, $string2); }
75 function publicCall() {return true;}
79 class remote_plugin_testplugin extends RemotePlugin {
80 function _getMethods() {
81 return array(
82 'method1' => array(
83 'args' => array(),
84 'return' => 'void'
85 ), 'methodString' => array(
86 'args' => array(),
87 'return' => 'string'
88 ), 'method2' => array(
89 'args' => array('string', 'int'),
90 'return' => 'array',
91 'name' => 'method2',
92 ), 'method2ext' => array(
93 'args' => array('string', 'int', 'bool'),
94 'return' => 'array',
95 'name' => 'method2',
96 ), 'publicCall' => array(
97 'args' => array(),
98 'return' => 'boolean',
99 'doc' => 'testing for public access',
100 'name' => 'publicCall',
101 'public' => 1
106 function method1() { return null; }
107 function methodString() { return 'success'; }
108 function method2($str, $int, $bool = false) { return array($str, $int, $bool); }
109 function publicCall() {return true;}
112 class remote_plugin_testplugin2 extends RemotePlugin {
114 * This is a dummy method
116 * @param string $str some more parameter description
117 * @param int $int
118 * @param bool $bool
119 * @param Object $unknown
120 * @return array
122 public function commented($str, $int, $bool, $unknown) { return array($str, $int, $bool); }
124 private function privateMethod() {return true;}
125 protected function protectedMethod() {return true;}
126 public function _underscore() {return true;}
131 class remote_test extends DokuWikiTest {
133 protected $userinfo;
135 /** @var Api */
136 protected $remote;
138 function setUp() : void {
139 parent::setUp();
140 global $plugin_controller;
141 global $conf;
142 global $USERINFO;
143 global $auth;
145 parent::setUp();
147 // mock plugin controller to return our test plugins
148 $pluginManager = $this->createMock('dokuwiki\Extension\PluginController');
149 $pluginManager->method('getList')->willReturn(array('testplugin', 'testplugin2'));
150 $pluginManager->method('load')->willReturnCallback(
151 function($type, $plugin) {
152 if($plugin == 'testplugin2') {
153 return new remote_plugin_testplugin2();
154 } else {
155 return new remote_plugin_testplugin();
159 $plugin_controller = $pluginManager;
161 $conf['remote'] = 1;
162 $conf['remoteuser'] = '!!not set!!';
163 $conf['useacl'] = 0;
165 $this->userinfo = $USERINFO;
166 $this->remote = new Api();
168 $auth = new AuthPlugin();
171 function tearDown() : void {
172 global $USERINFO;
173 $USERINFO = $this->userinfo;
177 function test_pluginMethods() {
178 $methods = $this->remote->getPluginMethods();
179 $actual = array_keys($methods);
180 sort($actual);
181 $expect = array(
182 'plugin.testplugin.method1',
183 'plugin.testplugin.method2',
184 'plugin.testplugin.methodString',
185 'plugin.testplugin.method2ext',
186 'plugin.testplugin.publicCall',
188 'plugin.testplugin2.commented'
190 sort($expect);
191 $this->assertEquals($expect,$actual);
194 function test_pluginDescriptors() {
195 $methods = $this->remote->getPluginMethods();
196 $this->assertEquals(array('string','int','bool','string'), $methods['plugin.testplugin2.commented']['args']);
197 $this->assertEquals('array', $methods['plugin.testplugin2.commented']['return']);
198 $this->assertEquals(0, $methods['plugin.testplugin2.commented']['public']);
199 $this->assertStringContainsString('This is a dummy method', $methods['plugin.testplugin2.commented']['doc']);
200 $this->assertStringContainsString('string $str some more parameter description', $methods['plugin.testplugin2.commented']['doc']);
203 function test_hasAccessSuccess() {
204 global $conf;
205 $conf['remoteuser'] = '';
206 $this->assertTrue($this->remote->hasAccess());
209 function test_hasAccessFail() {
210 global $conf;
211 $conf['remote'] = 0;
212 // the hasAccess() should throw a Exception to keep the same semantics with xmlrpc.php.
213 // because the user(xmlrpc) check remote before .--> (!$conf['remote']) die('XML-RPC server not enabled.');
214 // so it must be a Exception when get here.
215 $this->expectException(\dokuwiki\Remote\AccessDeniedException::class);
216 $this->remote->hasAccess();
219 function test_hasAccessFailAcl() {
220 global $conf;
221 $conf['useacl'] = 1;
222 $this->assertFalse($this->remote->hasAccess());
225 function test_hasAccessSuccessAclEmptyRemoteUser() {
226 global $conf;
227 $conf['useacl'] = 1;
228 $conf['remoteuser'] = '';
230 $this->assertTrue($this->remote->hasAccess());
233 function test_hasAccessSuccessAcl() {
234 global $conf;
235 global $USERINFO;
236 $conf['useacl'] = 1;
237 $conf['remoteuser'] = '@grp,@grp2';
238 $USERINFO['grps'] = array('grp');
239 $this->assertTrue($this->remote->hasAccess());
242 function test_hasAccessFailAcl2() {
243 global $conf;
244 global $USERINFO;
245 $conf['useacl'] = 1;
246 $conf['remoteuser'] = '@grp';
247 $USERINFO['grps'] = array('grp1');
249 $this->assertFalse($this->remote->hasAccess());
253 function test_forceAccessSuccess() {
254 global $conf;
255 $conf['remote'] = 1;
256 $conf['remoteuser'] = '';
257 $this->remote->forceAccess(); // no exception should occur
258 $this->assertTrue(true); // avoid being marked as risky for having no assertion
261 function test_forceAccessFail() {
262 global $conf;
263 $conf['remote'] = 0;
265 try {
266 $this->remote->forceAccess();
267 $this->fail('Expects RemoteException to be raised');
268 } catch (RemoteException $th) {
269 $this->assertEquals(-32604, $th->getCode());
273 function test_generalCoreFunctionWithoutArguments() {
274 global $conf;
275 global $USERINFO;
276 $conf['remote'] = 1;
277 $conf['remoteuser'] = '';
278 $conf['useacl'] = 1;
279 $USERINFO['grps'] = array('grp');
280 $remoteApi = new Api();
281 $remoteApi->getCoreMethods(new RemoteAPICoreTest());
283 $this->assertEquals($remoteApi->call('wiki.stringTestMethod'), 'success');
284 $this->assertEquals($remoteApi->call('wiki.intTestMethod'), 42);
285 $this->assertEquals($remoteApi->call('wiki.floatTestMethod'), 3.14159265);
286 $this->assertEquals($remoteApi->call('wiki.dateTestMethod'), 2623452346);
287 $this->assertEquals($remoteApi->call('wiki.fileTestMethod'), 'file content');
288 $this->assertEquals($remoteApi->call('wiki.voidTestMethod'), null);
291 function test_generalCoreFunctionOnArgumentMismatch() {
292 global $conf;
293 $conf['remote'] = 1;
294 $remoteApi = new Api();
295 $remoteApi->getCoreMethods(new RemoteAPICoreTest());
297 try {
298 $remoteApi->call('wiki.voidTestMethod', array('something'));
299 $this->fail('Expects RemoteException to be raised');
300 } catch (RemoteException $th) {
301 $this->assertEquals(-32604, $th->getCode());
305 function test_generalCoreFunctionWithArguments() {
306 global $conf;
307 global $USERINFO;
308 $conf['remote'] = 1;
309 $conf['remoteuser'] = '';
310 $conf['useacl'] = 1;
312 $remoteApi = new Api();
313 $remoteApi->getCoreMethods(new RemoteAPICoreTest());
315 $this->assertEquals($remoteApi->call('wiki.oneStringArgMethod', array('string')), 'string');
316 $this->assertEquals($remoteApi->call('wiki.twoArgMethod', array('string', 1)), array('string' , 1));
317 $this->assertEquals($remoteApi->call('wiki.twoArgWithDefaultArg', array('string')), array('string', 'default'));
318 $this->assertEquals($remoteApi->call('wiki.twoArgWithDefaultArg', array('string', 'another')), array('string', 'another'));
321 function test_generalCoreFunctionOnArgumentMissing() {
322 global $conf;
323 $conf['remote'] = 1;
324 $conf['remoteuser'] = '';
325 $remoteApi = new Api();
326 $remoteApi->getCoreMethods(new RemoteAPICoreTest());
328 try {
329 $remoteApi->call('wiki.twoArgWithDefaultArg', array());
330 $this->fail('Expects RemoteException to be raised');
331 } catch (RemoteException $th) {
332 $this->assertEquals(-32603, $th->getCode());
336 function test_pluginCallMethods() {
337 global $conf;
338 global $USERINFO;
339 $conf['remote'] = 1;
340 $conf['remoteuser'] = '';
341 $conf['useacl'] = 1;
343 $remoteApi = new Api();
344 $this->assertEquals($remoteApi->call('plugin.testplugin.method1'), null);
345 $this->assertEquals($remoteApi->call('plugin.testplugin.method2', array('string', 7)), array('string', 7, false));
346 $this->assertEquals($remoteApi->call('plugin.testplugin.method2ext', array('string', 7, true)), array('string', 7, true));
347 $this->assertEquals($remoteApi->call('plugin.testplugin.methodString'), 'success');
350 function test_pluginCallMethodsOnArgumentMissing() {
351 global $conf;
352 $conf['remote'] = 1;
353 $conf['remoteuser'] = '';
354 $remoteApi = new Api();
355 $remoteApi->getCoreMethods(new RemoteAPICoreTest());
357 try {
358 $remoteApi->call('plugin.testplugin.method2', array());
359 $this->fail('Expects RemoteException to be raised');
360 } catch (RemoteException $th) {
361 $this->assertEquals(-32603, $th->getCode());
365 function test_notExistingCall() {
366 global $conf;
367 $conf['remote'] = 1;
369 $this->expectException(RemoteException::class);
370 $this->expectExceptionCode(-32603);
372 $remoteApi = new Api();
373 $remoteApi->call('invalid method'); // no '.'
374 $remoteApi->call('does.not exist'); // unknown method type
377 function test_publicCallCore() {
378 global $conf;
379 $conf['useacl'] = 1;
380 $remoteApi = new Api();
381 $remoteApi->getCoreMethods(new RemoteAPICoreTest());
382 $this->assertTrue($remoteApi->call('wiki.publicCall'));
385 function test_publicCallPlugin() {
386 global $conf;
387 $conf['useacl'] = 1;
388 $remoteApi = new Api();
389 $this->assertTrue($remoteApi->call('plugin.testplugin.publicCall'));
392 function test_publicCallCoreDeny() {
393 global $conf;
394 $conf['useacl'] = 1;
395 $this->expectException(\dokuwiki\Remote\AccessDeniedException::class);
396 $remoteApi = new Api();
397 $remoteApi->getCoreMethods(new RemoteAPICoreTest());
398 $remoteApi->call('wiki.stringTestMethod');
401 function test_publicCallPluginDeny() {
402 global $conf;
403 $conf['useacl'] = 1;
404 $this->expectException(\dokuwiki\Remote\AccessDeniedException::class);
405 $remoteApi = new Api();
406 $remoteApi->call('plugin.testplugin.methodString');
409 function test_pluginCallCustomPath() {
410 global $conf;
411 global $USERINFO;
412 $conf['remote'] = 1;
413 $conf['remoteuser'] = '';
414 $conf['useacl'] = 1;
415 global $EVENT_HANDLER;
416 $EVENT_HANDLER->register_hook('RPC_CALL_ADD', 'BEFORE', $this, 'pluginCallCustomPathRegister');
418 $remoteApi = new Api();
419 $result = $remoteApi->call('custom.path');
420 $this->assertEquals($result, 'success');
423 function pluginCallCustomPathRegister(&$event, $param) {
424 $event->data['custom.path'] = array('testplugin', 'methodString');