1 | <?php |
||||||||
2 | |||||||||
3 | namespace TheAentMachine\Registry; |
||||||||
4 | |||||||||
5 | use PHPUnit\Framework\TestCase; |
||||||||
6 | use TheAentMachine\Aenthill\CommonMetadata; |
||||||||
0 ignored issues
–
show
|
|||||||||
7 | use TheAentMachine\Service\Enum\VolumeTypeEnum; |
||||||||
8 | use TheAentMachine\Service\Environment\SharedEnvVariable; |
||||||||
9 | use TheAentMachine\Service\Exception\ServiceException; |
||||||||
10 | use TheAentMachine\Service\Service; |
||||||||
11 | use TheAentMachine\Service\Volume\BindVolume; |
||||||||
12 | use TheAentMachine\Service\Volume\NamedVolume; |
||||||||
13 | |||||||||
14 | class ServiceTest extends TestCase |
||||||||
15 | { |
||||||||
16 | private const VALID_PAYLOAD = <<< 'JSON' |
||||||||
17 | { |
||||||||
18 | "serviceName" : "foo", |
||||||||
19 | "service": { |
||||||||
20 | "image" : "foo/bar:baz", |
||||||||
21 | "command" : ["foo", "-bar", "-baz", "--qux"], |
||||||||
22 | "internalPorts" : [1, 2, 3], |
||||||||
23 | "dependsOn" : ["foo", "bar"], |
||||||||
24 | "ports" : [{"source": 80, "target": 8080, "comment": "a line of comment"}], |
||||||||
25 | "environment" : { |
||||||||
26 | "FOO": {"value": "foo", "type": "sharedEnvVariable", "comment": "foo", "containerId": "baz"}, |
||||||||
27 | "BAR": {"value": "bar", "type": "sharedSecret", "comment": "bar"}, |
||||||||
28 | "BAZ": {"value": "baz", "type": "imageEnvVariable", "comment": "baz"}, |
||||||||
29 | "QUX": {"value": "qux", "type": "containerEnvVariable", "comment": "qux"} |
||||||||
30 | }, |
||||||||
31 | "labels" : { |
||||||||
32 | "foo": {"value": "fooo", "comment": "fooo"}, |
||||||||
33 | "bar": {"value": "baar", "comment": "baar"} |
||||||||
34 | }, |
||||||||
35 | "volumes" : [ |
||||||||
36 | {"type": "volume", "source": "foo", "target": "/foo", "readOnly": true, "comment": "it's a named volume tho", "requestStorage": "8Gi"}, |
||||||||
37 | {"type": "bind", "source": "/bar", "target": "/bar", "readOnly": false, "comment": "a bind volume"}, |
||||||||
38 | {"type": "tmpfs", "source": "baz", "comment": "a tmpfs"} |
||||||||
39 | ], |
||||||||
40 | "virtualHosts": [ |
||||||||
41 | {"host": "foo", "port": 80, "comment": "a default virtual host"}, |
||||||||
42 | {"port": 8080, "comment": "it's ok"}, |
||||||||
43 | {"hostPrefix": "foo", "port": 80} |
||||||||
44 | ], |
||||||||
45 | "needBuild": true |
||||||||
46 | }, |
||||||||
47 | "dockerfileCommands": [ |
||||||||
48 | "RUN composer install" |
||||||||
49 | ], |
||||||||
50 | "destEnvTypes": [ |
||||||||
51 | "DEV" |
||||||||
52 | ], |
||||||||
53 | "resources": { |
||||||||
54 | "requests": { |
||||||||
55 | "memory": "64Mi", |
||||||||
56 | "cpu": "250m" |
||||||||
57 | }, |
||||||||
58 | "limits": { |
||||||||
59 | "memory": "128Mi", |
||||||||
60 | "cpu": "500m" |
||||||||
61 | } |
||||||||
62 | } |
||||||||
63 | } |
||||||||
64 | JSON; |
||||||||
65 | |||||||||
66 | private const MISSING_SERVICE_NAME_PAYLOAD = <<< 'JSON' |
||||||||
67 | { |
||||||||
68 | "service": { |
||||||||
69 | "internalPorts": [80] |
||||||||
70 | } |
||||||||
71 | } |
||||||||
72 | JSON; |
||||||||
73 | |||||||||
74 | private const UNKNOWN_ENV_VARIABLE_TYPE_PAYLOAD = <<< 'JSON' |
||||||||
75 | { |
||||||||
76 | "serviceName": "foo", |
||||||||
77 | "service": { |
||||||||
78 | "environment": { |
||||||||
79 | "FOO": { |
||||||||
80 | "value": "fooo", |
||||||||
81 | "type": "YIKES_THATS_SOME_BAD_TYPE_HERE" |
||||||||
82 | } |
||||||||
83 | } |
||||||||
84 | } |
||||||||
85 | } |
||||||||
86 | JSON; |
||||||||
87 | |||||||||
88 | private const UNKNOWN_VOLUME_TYPE_PAYLOAD = <<< 'JSON' |
||||||||
89 | { |
||||||||
90 | "serviceName": "foo", |
||||||||
91 | "service": { |
||||||||
92 | "volumes": [ |
||||||||
93 | { |
||||||||
94 | "type": "AGAIN?WTH", |
||||||||
95 | "source": "foo" |
||||||||
96 | } |
||||||||
97 | ] |
||||||||
98 | } |
||||||||
99 | } |
||||||||
100 | JSON; |
||||||||
101 | |||||||||
102 | /** @throws ServiceException */ |
||||||||
103 | public function testValidPayload(): void |
||||||||
104 | { |
||||||||
105 | $array = \GuzzleHttp\json_decode(self::VALID_PAYLOAD, true); |
||||||||
106 | $service = Service::parsePayload($array); |
||||||||
107 | $out = $service->jsonSerialize(); |
||||||||
108 | $this->assertEquals($array, $out); |
||||||||
109 | $this->assertTrue($service->isForDevEnvType()); |
||||||||
0 ignored issues
–
show
The method
isForDevEnvType() does not exist on TheAentMachine\Service\Service .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
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.
Loading history...
|
|||||||||
110 | $this->assertFalse($service->isForTestEnvType()); |
||||||||
0 ignored issues
–
show
The method
isForTestEnvType() does not exist on TheAentMachine\Service\Service .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
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.
Loading history...
|
|||||||||
111 | $this->assertFalse($service->isForProdEnvType()); |
||||||||
0 ignored issues
–
show
The method
isForProdEnvType() does not exist on TheAentMachine\Service\Service .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
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.
Loading history...
|
|||||||||
112 | } |
||||||||
113 | |||||||||
114 | /** @throws ServiceException */ |
||||||||
115 | public function testMissingServiceNamePayload(): void |
||||||||
116 | { |
||||||||
117 | $this->expectException(ServiceException::class); |
||||||||
118 | $array = \GuzzleHttp\json_decode(self::MISSING_SERVICE_NAME_PAYLOAD, true); |
||||||||
119 | Service::parsePayload($array)->jsonSerialize(); |
||||||||
120 | } |
||||||||
121 | |||||||||
122 | /** @throws ServiceException */ |
||||||||
123 | public function testUnknownEnvVariableTypePayload(): void |
||||||||
124 | { |
||||||||
125 | $this->expectException(ServiceException::class); |
||||||||
126 | $array = \GuzzleHttp\json_decode(self::UNKNOWN_ENV_VARIABLE_TYPE_PAYLOAD, true); |
||||||||
127 | Service::parsePayload($array)->jsonSerialize(); |
||||||||
128 | } |
||||||||
129 | |||||||||
130 | /** @throws ServiceException */ |
||||||||
131 | public function testUnknownVolumeTypePayload(): void |
||||||||
132 | { |
||||||||
133 | $this->expectException(ServiceException::class); |
||||||||
134 | $array = \GuzzleHttp\json_decode(self::UNKNOWN_VOLUME_TYPE_PAYLOAD, true); |
||||||||
135 | Service::parsePayload($array)->jsonSerialize(); |
||||||||
136 | } |
||||||||
137 | |||||||||
138 | /** @throws ServiceException */ |
||||||||
139 | public function testSettersAndAdders(): void |
||||||||
140 | { |
||||||||
141 | $s = new Service(); |
||||||||
142 | $s->setServiceName('foo'); |
||||||||
143 | $s->setImage('foo/bar:baz'); |
||||||||
144 | $s->setCommand(['foo', '-bar', '-baz']); |
||||||||
145 | $s->addCommand('--qux'); |
||||||||
146 | $s->setInternalPorts([1, 2]); |
||||||||
147 | $s->addInternalPort(3); |
||||||||
148 | $s->setDependsOn(['foo']); |
||||||||
149 | $s->addDependsOn('bar'); |
||||||||
150 | $s->addPort(80, 8080, 'a line of comment'); |
||||||||
151 | $s->addLabel('foo', 'fooo', 'fooo'); |
||||||||
152 | $s->addLabel('bar', 'baar', 'baar'); |
||||||||
153 | $s->addSharedEnvVariable('FOO', 'foo', 'foo', 'baz'); |
||||||||
154 | $s->addSharedSecret('BAR', 'bar', 'bar'); |
||||||||
155 | $s->addImageEnvVariable('BAZ', 'baz', 'baz'); |
||||||||
156 | $s->addContainerEnvVariable('QUX', 'qux', 'qux'); |
||||||||
157 | $s->addNamedVolume('foo', '/foo', true, 'it\'s a named volume tho', '8Gi'); |
||||||||
158 | $s->addBindVolume('/bar', '/bar', false, 'a bind volume'); |
||||||||
159 | $s->addTmpfsVolume('baz', 'a tmpfs'); |
||||||||
160 | $s->addDockerfileCommand('RUN composer install'); |
||||||||
161 | $s->addVirtualHost('foo', 80, 'a default virtual host'); |
||||||||
0 ignored issues
–
show
The call to
TheAentMachine\Service\Service::addVirtualHost() has too many arguments starting with 80 .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.
Loading history...
'foo' of type string is incompatible with the type integer expected by parameter $port of TheAentMachine\Service\Service::addVirtualHost() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||||
162 | $s->addVirtualHost(null, 8080, "it's ok"); |
||||||||
0 ignored issues
–
show
null of type null is incompatible with the type integer expected by parameter $port of TheAentMachine\Service\Service::addVirtualHost() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||||||
163 | $s->addVirtualHostPrefix('foo', 80, null); |
||||||||
0 ignored issues
–
show
The method
addVirtualHostPrefix() does not exist on TheAentMachine\Service\Service . Did you maybe mean addVirtualHost() ?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
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.
Loading history...
|
|||||||||
164 | $s->setNeedBuild(true); |
||||||||
165 | $s->addDestEnvType(CommonMetadata::ENV_TYPE_DEV, true); |
||||||||
0 ignored issues
–
show
The method
addDestEnvType() does not exist on TheAentMachine\Service\Service .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
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.
Loading history...
|
|||||||||
166 | $s->setRequestMemory('64Mi'); |
||||||||
167 | $s->setRequestCpu('250m'); |
||||||||
168 | $s->setLimitMemory('128Mi'); |
||||||||
169 | $s->setLimitCpu('500m'); |
||||||||
170 | $outArray = $s->jsonSerialize(); |
||||||||
171 | $expectedArray = \GuzzleHttp\json_decode(self::VALID_PAYLOAD, true); |
||||||||
172 | $this->assertEquals($outArray, $expectedArray); |
||||||||
173 | |||||||||
174 | $outArray = $s->imageJsonSerialize(); |
||||||||
175 | $expectedArray = [ |
||||||||
176 | 'serviceName' => 'foo', |
||||||||
177 | 'dockerfileCommands' => [ |
||||||||
178 | 'FROM foo/bar:baz', |
||||||||
179 | 'ENV BAZ=baz', |
||||||||
180 | 'COPY /bar /bar', |
||||||||
181 | 'CMD foo -bar -baz --qux', |
||||||||
182 | 'RUN composer install' |
||||||||
183 | ], |
||||||||
184 | 'destEnvTypes' => ['DEV'] |
||||||||
185 | ]; |
||||||||
186 | $this->assertEquals($outArray, $expectedArray); |
||||||||
187 | } |
||||||||
188 | |||||||||
189 | /** @throws ServiceException */ |
||||||||
190 | public function testInvalidRequestMemoryPattern(): void |
||||||||
191 | { |
||||||||
192 | $s = new Service(); |
||||||||
193 | $s->setServiceName('foo'); |
||||||||
194 | $s->setRequestMemory('0.5Zi'); |
||||||||
195 | $this->expectException(ServiceException::class); |
||||||||
196 | $s->jsonSerialize(); |
||||||||
197 | } |
||||||||
198 | |||||||||
199 | /** @throws ServiceException */ |
||||||||
200 | public function testInvalidRequestCpuPattern(): void |
||||||||
201 | { |
||||||||
202 | $s = new Service(); |
||||||||
203 | $s->setServiceName('foo'); |
||||||||
204 | $s->setRequestCpu('0,1'); |
||||||||
205 | $this->expectException(ServiceException::class); |
||||||||
206 | $s->jsonSerialize(); |
||||||||
207 | } |
||||||||
208 | |||||||||
209 | public function testVolumeRemovers(): void |
||||||||
210 | { |
||||||||
211 | $s = new Service(); |
||||||||
212 | $s->setServiceName('my-service'); |
||||||||
213 | $s->addBindVolume('./foo', '/opt/app/foo', true); |
||||||||
214 | $s->addBindVolume('./bar', '/opt/app/baz', false); |
||||||||
215 | $s->addNamedVolume('my-data', '/data', true); |
||||||||
216 | $s->removeVolumesBySource('./bar'); |
||||||||
217 | /** @var BindVolume[]|NamedVolume[] $volumes */ |
||||||||
218 | $volumes = $s->getVolumes(); |
||||||||
219 | $this->assertEquals(count($volumes), 2); |
||||||||
220 | $this->assertEquals($volumes[0]->getType(), VolumeTypeEnum::BIND_VOLUME); |
||||||||
221 | $this->assertEquals($volumes[0]->getSource(), './foo'); |
||||||||
222 | $this->assertEquals($volumes[1]->getType(), VolumeTypeEnum::NAMED_VOLUME); |
||||||||
223 | |||||||||
224 | $s->addBindVolume('./bar', '/opt/app/baz', false); |
||||||||
225 | $s->removeAllBindVolumes(); |
||||||||
226 | $volumes = $s->getVolumes(); |
||||||||
227 | $this->assertEquals(count($volumes), 1); |
||||||||
228 | $this->assertEquals($volumes[0]->getType(), VolumeTypeEnum::NAMED_VOLUME); |
||||||||
229 | $this->assertEquals($volumes[0]->getTarget(), '/data'); |
||||||||
230 | } |
||||||||
231 | |||||||||
232 | public function testEnvVariableContains(): void |
||||||||
233 | { |
||||||||
234 | $s = new Service(); |
||||||||
235 | $s->setServiceName('my-service'); |
||||||||
236 | $s->addSharedSecret('MYSQL_ROOT_PASSWORD', 'foo', 'comment', 'container'); |
||||||||
237 | self::assertCount(0, $s->getAllSharedEnvVariable()); |
||||||||
238 | self::assertCount(1, $s->getAllSharedSecret()); |
||||||||
239 | self::assertCount(0, $s->getAllImageEnvVariable()); |
||||||||
240 | self::assertCount(0, $s->getAllContainerEnvVariable()); |
||||||||
241 | $variable = $s->getAllSharedSecret()['MYSQL_ROOT_PASSWORD']; |
||||||||
242 | $this->assertInstanceOf(SharedEnvVariable::class, $variable); |
||||||||
243 | $this->assertSame('foo', $variable->getValue()); |
||||||||
244 | $this->assertSame('comment', $variable->getComment()); |
||||||||
245 | $this->assertSame('container', $variable->getContainerId()); |
||||||||
246 | } |
||||||||
247 | } |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths