|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* This file is part of the tarantool/client package. |
|
5
|
|
|
* |
|
6
|
|
|
* (c) Eugene Leonovich <[email protected]> |
|
7
|
|
|
* |
|
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
|
9
|
|
|
* file that was distributed with this source code. |
|
10
|
|
|
*/ |
|
11
|
|
|
|
|
12
|
|
|
declare(strict_types=1); |
|
13
|
|
|
|
|
14
|
|
|
namespace Tarantool\Client\Tests\Integration; |
|
15
|
|
|
|
|
16
|
|
|
use Tarantool\Client\Error; |
|
17
|
|
|
use Tarantool\Client\Exception\RequestFailed; |
|
18
|
|
|
|
|
19
|
|
|
final class BoxErrorTest extends TestCase |
|
20
|
|
|
{ |
|
21
|
|
|
public function testExceptionIsThrown() : void |
|
22
|
|
|
{ |
|
23
|
|
|
$this->expectException(RequestFailed::class); |
|
24
|
|
|
$this->expectExceptionMessage('Because I can'); |
|
25
|
|
|
$this->expectExceptionCode(42); |
|
26
|
|
|
|
|
27
|
|
|
$this->client->evaluate('box.error({code = 42, reason = "Because I can"})'); |
|
|
|
|
|
|
28
|
|
|
} |
|
29
|
|
|
|
|
30
|
|
|
/** |
|
31
|
|
|
* @requires Tarantool >=2.4.1 |
|
32
|
|
|
*/ |
|
33
|
|
|
public function testExceptionWithErrorIsThrown() : void |
|
34
|
|
|
{ |
|
35
|
|
|
try { |
|
36
|
|
|
/* |
|
37
|
|
|
* Triggers "AccessDeniedError", which includes the fields |
|
38
|
|
|
* "object_type", "object_name", "access_type", "user" (since 3.1). |
|
39
|
|
|
* See https://www.tarantool.io/en/doc/2.4/dev_guide/internals/box_protocol/#binary-protocol-responses-for-errors-extra. |
|
40
|
|
|
*/ |
|
41
|
|
|
$this->client->evaluate(" |
|
42
|
|
|
local temp_user = 'user_with_no_privileges' |
|
43
|
|
|
local curr_user = box.session.user() |
|
44
|
|
|
box.schema.user.create(temp_user) |
|
45
|
|
|
box.session.su(temp_user) |
|
46
|
|
|
local _, err = pcall(box.schema.user.grant, temp_user, 'execute', 'universe') |
|
47
|
|
|
box.session.su(curr_user) |
|
48
|
|
|
box.schema.user.drop(temp_user) |
|
49
|
|
|
box.error(err) |
|
50
|
|
|
"); |
|
51
|
|
|
self::fail(sprintf('"%s" exception was not thrown', RequestFailed::class)); |
|
52
|
|
|
} catch (RequestFailed $e) { |
|
53
|
|
|
self::assertSame("Write access to space '_priv' is denied for user 'user_with_no_privileges'", $e->getMessage()); |
|
54
|
|
|
self::assertSame(42, $e->getCode()); |
|
55
|
|
|
|
|
56
|
|
|
$error = $e->getError(); |
|
57
|
|
|
self::assertInstanceOf(Error::class, $error); |
|
58
|
|
|
self::assertSame('AccessDeniedError', $error->getType()); |
|
59
|
|
|
self::assertSame("Write access to space '_priv' is denied for user 'user_with_no_privileges'", $error->getMessage()); |
|
60
|
|
|
self::assertSame(42, $error->getCode()); |
|
61
|
|
|
$expectedFields = [ |
|
62
|
|
|
'object_type' => 'space', |
|
63
|
|
|
'object_name' => '_priv', |
|
64
|
|
|
'access_type' => 'Write', |
|
65
|
|
|
'user' => 'user_with_no_privileges', |
|
66
|
|
|
]; |
|
67
|
|
|
if ($this->tarantoolVersionSatisfies('< 3.1')) { |
|
68
|
|
|
unset($expectedFields['user']); |
|
69
|
|
|
} |
|
70
|
|
|
self::assertEquals($expectedFields, $error->getFields()); |
|
71
|
|
|
self::assertNull($error->getPrevious()); |
|
72
|
|
|
} |
|
73
|
|
|
} |
|
74
|
|
|
|
|
75
|
|
|
/** |
|
76
|
|
|
* @requires Tarantool >=2.4.1 |
|
77
|
|
|
*/ |
|
78
|
|
|
public function testExceptionWithNestedErrorIsThrown() : void |
|
79
|
|
|
{ |
|
80
|
|
|
try { |
|
81
|
|
|
$this->client->evaluate(' |
|
82
|
|
|
err1 = box.error.new({code = 1, type = "t1", reason = "r1"}) |
|
83
|
|
|
err2 = box.error.new({code = 2, type = "t2", reason = "r2",}) |
|
84
|
|
|
err1:set_prev(err2) |
|
85
|
|
|
box.error(err1) |
|
86
|
|
|
'); |
|
87
|
|
|
self::fail(sprintf('"%s" exception was not thrown', RequestFailed::class)); |
|
88
|
|
|
} catch (RequestFailed $e) { |
|
89
|
|
|
self::assertSame('r1', $e->getMessage()); |
|
90
|
|
|
self::assertSame(1, $e->getCode()); |
|
91
|
|
|
|
|
92
|
|
|
$error = $e->getError(); |
|
93
|
|
|
self::assertInstanceOf(Error::class, $error); |
|
94
|
|
|
self::assertSame('CustomError', $error->getType()); |
|
95
|
|
|
self::assertSame('r1', $error->getMessage()); |
|
96
|
|
|
self::assertSame(1, $error->getCode()); |
|
97
|
|
|
self::assertSame(['custom_type' => 't1'], $error->getFields()); |
|
98
|
|
|
|
|
99
|
|
|
$prevError = $error->getPrevious(); |
|
100
|
|
|
self::assertInstanceOf(Error::class, $prevError); |
|
101
|
|
|
self::assertSame('CustomError', $prevError->getType()); |
|
102
|
|
|
self::assertSame('r2', $prevError->getMessage()); |
|
103
|
|
|
self::assertSame(2, $prevError->getCode()); |
|
104
|
|
|
self::assertSame(['custom_type' => 't2'], $prevError->getFields()); |
|
105
|
|
|
self::assertNull($prevError->getPrevious()); |
|
106
|
|
|
} |
|
107
|
|
|
} |
|
108
|
|
|
} |
|
109
|
|
|
|
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.
This is most likely a typographical error or the method has been renamed.