1<?php
2
3require_once('generated/Descriptors/TestDescriptorsEnum.php');
4require_once('generated/Descriptors/TestDescriptorsMessage.php');
5require_once('test_base.php');
6require_once('test_util.php');
7
8use Google\Protobuf\DescriptorPool;
9use Google\Protobuf\Internal\RepeatedField;
10use Google\Protobuf\Internal\MapField;
11use Descriptors\TestDescriptorsEnum;
12use Descriptors\TestDescriptorsMessage;
13use Descriptors\TestDescriptorsMessage\Sub;
14
15class DescriptorsTest extends TestBase
16{
17
18    // Redefine these here for compatibility with c extension
19    const GPBLABEL_OPTIONAL = 1;
20    const GPBLABEL_REQUIRED = 2;
21    const GPBLABEL_REPEATED = 3;
22
23    const GPBTYPE_DOUBLE   =  1;
24    const GPBTYPE_FLOAT    =  2;
25    const GPBTYPE_INT64    =  3;
26    const GPBTYPE_UINT64   =  4;
27    const GPBTYPE_INT32    =  5;
28    const GPBTYPE_FIXED64  =  6;
29    const GPBTYPE_FIXED32  =  7;
30    const GPBTYPE_BOOL     =  8;
31    const GPBTYPE_STRING   =  9;
32    const GPBTYPE_GROUP    = 10;
33    const GPBTYPE_MESSAGE  = 11;
34    const GPBTYPE_BYTES    = 12;
35    const GPBTYPE_UINT32   = 13;
36    const GPBTYPE_ENUM     = 14;
37    const GPBTYPE_SFIXED32 = 15;
38    const GPBTYPE_SFIXED64 = 16;
39    const GPBTYPE_SINT32   = 17;
40    const GPBTYPE_SINT64   = 18;
41
42    #########################################################
43    # Test descriptor pool.
44    #########################################################
45
46    public function testDescriptorPool()
47    {
48        $pool = DescriptorPool::getGeneratedPool();
49
50        $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage()));
51        $this->assertInstanceOf('\Google\Protobuf\Descriptor', $desc);
52
53        $enumDesc = $pool->getEnumDescriptorByClassName(get_class(new TestDescriptorsEnum()));
54        $this->assertInstanceOf('\Google\Protobuf\EnumDescriptor', $enumDesc);
55    }
56
57    public function testDescriptorPoolIncorrectArgs()
58    {
59        $pool = DescriptorPool::getGeneratedPool();
60
61        $desc = $pool->getDescriptorByClassName('NotAClass');
62        $this->assertNull($desc);
63
64        $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsEnum()));
65        $this->assertNull($desc);
66
67        $enumDesc = $pool->getEnumDescriptorByClassName(get_class(new TestDescriptorsMessage()));
68        $this->assertNull($enumDesc);
69    }
70
71    #########################################################
72    # Test descriptor.
73    #########################################################
74
75    public function testDescriptor()
76    {
77        $pool = DescriptorPool::getGeneratedPool();
78        $class = get_class(new TestDescriptorsMessage());
79        $this->assertSame('Descriptors\TestDescriptorsMessage', $class);
80        $desc = $pool->getDescriptorByClassName($class);
81
82        $this->assertSame('descriptors.TestDescriptorsMessage', $desc->getFullName());
83        $this->assertSame($class, $desc->getClass());
84
85        $this->assertInstanceOf('\Google\Protobuf\FieldDescriptor', $desc->getField(0));
86        $this->assertSame(7, $desc->getFieldCount());
87
88        $this->assertInstanceOf('\Google\Protobuf\OneofDescriptor', $desc->getOneofDecl(0));
89        $this->assertSame(1, $desc->getOneofDeclCount());
90    }
91
92    #########################################################
93    # Test enum descriptor.
94    #########################################################
95
96    public function testEnumDescriptor()
97    {
98        // WARNINIG - we need to do this so that TestDescriptorsEnum is registered!!?
99        new TestDescriptorsMessage();
100
101        $pool = DescriptorPool::getGeneratedPool();
102
103        $enumDesc = $pool->getEnumDescriptorByClassName(get_class(new TestDescriptorsEnum()));
104
105        // Build map of enum values
106        $enumDescMap = [];
107        for ($i = 0; $i < $enumDesc->getValueCount(); $i++) {
108            $enumValueDesc = $enumDesc->getValue($i);
109            $this->assertInstanceOf('\Google\Protobuf\EnumValueDescriptor', $enumValueDesc);
110            $enumDescMap[$enumValueDesc->getNumber()] = $enumValueDesc->getName();
111        }
112
113        $this->assertSame('ZERO', $enumDescMap[0]);
114        $this->assertSame('ONE', $enumDescMap[1]);
115
116        $this->assertSame(2, $enumDesc->getValueCount());
117    }
118
119    #########################################################
120    # Test field descriptor.
121    #########################################################
122
123    public function testFieldDescriptor()
124    {
125        $pool = DescriptorPool::getGeneratedPool();
126        $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage()));
127
128        $fieldDescMap = $this->buildFieldMap($desc);
129
130        // Optional int field
131        $fieldDesc = $fieldDescMap[1];
132        $this->assertSame('optional_int32', $fieldDesc->getName());
133        $this->assertSame(1, $fieldDesc->getNumber());
134        $this->assertSame(self::GPBLABEL_OPTIONAL, $fieldDesc->getLabel());
135        $this->assertSame(self::GPBTYPE_INT32, $fieldDesc->getType());
136        $this->assertFalse($fieldDesc->isMap());
137
138        // Optional enum field
139        $fieldDesc = $fieldDescMap[16];
140        $this->assertSame('optional_enum', $fieldDesc->getName());
141        $this->assertSame(16, $fieldDesc->getNumber());
142        $this->assertSame(self::GPBLABEL_OPTIONAL, $fieldDesc->getLabel());
143        $this->assertSame(self::GPBTYPE_ENUM, $fieldDesc->getType());
144        $this->assertInstanceOf('\Google\Protobuf\EnumDescriptor', $fieldDesc->getEnumType());
145        $this->assertFalse($fieldDesc->isMap());
146
147        // Optional message field
148        $fieldDesc = $fieldDescMap[17];
149        $this->assertSame('optional_message', $fieldDesc->getName());
150        $this->assertSame(17, $fieldDesc->getNumber());
151        $this->assertSame(self::GPBLABEL_OPTIONAL, $fieldDesc->getLabel());
152        $this->assertSame(self::GPBTYPE_MESSAGE, $fieldDesc->getType());
153        $this->assertInstanceOf('\Google\Protobuf\Descriptor', $fieldDesc->getMessageType());
154        $this->assertFalse($fieldDesc->isMap());
155
156        // Repeated int field
157        $fieldDesc = $fieldDescMap[31];
158        $this->assertSame('repeated_int32', $fieldDesc->getName());
159        $this->assertSame(31, $fieldDesc->getNumber());
160        $this->assertSame(self::GPBLABEL_REPEATED, $fieldDesc->getLabel());
161        $this->assertSame(self::GPBTYPE_INT32, $fieldDesc->getType());
162        $this->assertFalse($fieldDesc->isMap());
163
164        // Repeated message field
165        $fieldDesc = $fieldDescMap[47];
166        $this->assertSame('repeated_message', $fieldDesc->getName());
167        $this->assertSame(47, $fieldDesc->getNumber());
168        $this->assertSame(self::GPBLABEL_REPEATED, $fieldDesc->getLabel());
169        $this->assertSame(self::GPBTYPE_MESSAGE, $fieldDesc->getType());
170        $this->assertInstanceOf('\Google\Protobuf\Descriptor', $fieldDesc->getMessageType());
171        $this->assertFalse($fieldDesc->isMap());
172
173        // Oneof int field
174        // Tested further in testOneofDescriptor()
175        $fieldDesc = $fieldDescMap[51];
176        $this->assertSame('oneof_int32', $fieldDesc->getName());
177        $this->assertSame(51, $fieldDesc->getNumber());
178        $this->assertSame(self::GPBLABEL_OPTIONAL, $fieldDesc->getLabel());
179        $this->assertSame(self::GPBTYPE_INT32, $fieldDesc->getType());
180        $this->assertFalse($fieldDesc->isMap());
181
182        // Map int-enum field
183        $fieldDesc = $fieldDescMap[71];
184        $this->assertSame('map_int32_enum', $fieldDesc->getName());
185        $this->assertSame(71, $fieldDesc->getNumber());
186        $this->assertSame(self::GPBLABEL_REPEATED, $fieldDesc->getLabel());
187        $this->assertSame(self::GPBTYPE_MESSAGE, $fieldDesc->getType());
188        $this->assertTrue($fieldDesc->isMap());
189        $mapDesc = $fieldDesc->getMessageType();
190        $this->assertSame('descriptors.TestDescriptorsMessage.MapInt32EnumEntry', $mapDesc->getFullName());
191        $this->assertSame(self::GPBTYPE_INT32, $mapDesc->getField(0)->getType());
192        $this->assertSame(self::GPBTYPE_ENUM, $mapDesc->getField(1)->getType());
193    }
194
195    /**
196     * @expectedException \Exception
197     */
198    public function testFieldDescriptorEnumException()
199    {
200        $pool = DescriptorPool::getGeneratedPool();
201        $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage()));
202        $fieldDesc = $desc->getField(0);
203        $fieldDesc->getEnumType();
204    }
205
206    /**
207     * @expectedException \Exception
208     */
209    public function testFieldDescriptorMessageException()
210    {
211        $pool = DescriptorPool::getGeneratedPool();
212        $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage()));
213        $fieldDesc = $desc->getField(0);
214        $fieldDesc->getMessageType();
215    }
216
217    #########################################################
218    # Test oneof descriptor.
219    #########################################################
220
221    public function testOneofDescriptor()
222    {
223        $pool = DescriptorPool::getGeneratedPool();
224        $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage()));
225
226        $fieldDescMap = $this->buildFieldMap($desc);
227        $fieldDesc = $fieldDescMap[51];
228
229        $oneofDesc = $desc->getOneofDecl(0);
230
231        $this->assertSame('my_oneof', $oneofDesc->getName());
232        $fieldDescFromOneof = $oneofDesc->getField(0);
233        $this->assertSame($fieldDesc, $fieldDescFromOneof);
234        $this->assertSame(1, $oneofDesc->getFieldCount());
235    }
236
237    private function buildFieldMap($desc)
238    {
239        $fieldDescMap = [];
240        for ($i = 0; $i < $desc->getFieldCount(); $i++) {
241            $fieldDesc = $desc->getField($i);
242            $fieldDescMap[$fieldDesc->getNumber()] = $fieldDesc;
243        }
244        return $fieldDescMap;
245    }
246}
247