1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Negative Buffer API tests.
22 *//*--------------------------------------------------------------------*/
23
24#include "es2fNegativeBufferApiTests.hpp"
25#include "es2fApiCase.hpp"
26#include "gluContextInfo.hpp"
27
28#include "glwEnums.hpp"
29#include "glwDefs.hpp"
30
31using namespace glw; // GL types
32
33namespace deqp
34{
35namespace gles2
36{
37namespace Functional
38{
39
40using tcu::TestLog;
41
42NegativeBufferApiTests::NegativeBufferApiTests (Context& context)
43	: TestCaseGroup(context, "buffer", "Negative Buffer API Cases")
44{
45}
46
47NegativeBufferApiTests::~NegativeBufferApiTests (void)
48{
49}
50
51void NegativeBufferApiTests::init (void)
52{
53	ES2F_ADD_API_CASE(bind_buffer, "Invalid glBindBuffer() usage",
54		{
55			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if target is not one of the allowable values.");
56			glBindBuffer(-1, 0);
57			expectError(GL_INVALID_ENUM);
58			m_log << TestLog::EndSection;
59		});
60	ES2F_ADD_API_CASE(delete_buffers, "Invalid glDeleteBuffers() usage",
61		{
62			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if n is negative.");
63			glDeleteBuffers(-1, 0);
64			expectError(GL_INVALID_VALUE);
65			m_log << TestLog::EndSection;
66		});
67	ES2F_ADD_API_CASE(gen_buffers, "Invalid glGenBuffers() usage",
68		{
69			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if n is negative.");
70			glGenBuffers(-1, 0);
71			expectError(GL_INVALID_VALUE);
72			m_log << TestLog::EndSection;
73		});
74	ES2F_ADD_API_CASE(buffer_data, "Invalid glBufferData() usage",
75		{
76			GLuint buffer;
77			glGenBuffers(1, &buffer);
78			glBindBuffer(GL_ARRAY_BUFFER, buffer);
79
80			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if target is not GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER.");
81			glBufferData(-1, 0, NULL, GL_STREAM_DRAW);
82			expectError(GL_INVALID_ENUM);
83			m_log << TestLog::EndSection;
84
85			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if usage is not GL_STREAM_DRAW, GL_STATIC_DRAW, or GL_DYNAMIC_DRAW.");
86			glBufferData(GL_ARRAY_BUFFER, 0, NULL, -1);
87			expectError(GL_INVALID_ENUM);
88			m_log << TestLog::EndSection;
89
90			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if size is negative.");
91			glBufferData(GL_ARRAY_BUFFER, -1, NULL, GL_STREAM_DRAW);
92			expectError(GL_INVALID_VALUE);
93			m_log << TestLog::EndSection;
94
95			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if the reserved buffer object name 0 is bound to target.");
96			glBindBuffer(GL_ARRAY_BUFFER, 0);
97			glBufferData(GL_ARRAY_BUFFER, 0, NULL, GL_STREAM_DRAW);
98			expectError(GL_INVALID_OPERATION);
99			m_log << TestLog::EndSection;
100
101			glDeleteBuffers(1, &buffer);
102		});
103	ES2F_ADD_API_CASE(buffer_sub_data, "Invalid glBufferSubData() usage",
104		{
105			GLuint buffer;
106			glGenBuffers(1, &buffer);
107			glBindBuffer(GL_ARRAY_BUFFER, buffer);
108			glBufferData(GL_ARRAY_BUFFER, 10, 0, GL_STREAM_DRAW);
109
110			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if target is not GL_ARRAY_BUFFER or GL_ELEMENT_ARRAY_BUFFER.");
111			glBufferSubData(-1, 1, 1, 0);
112			expectError(GL_INVALID_ENUM);
113			m_log << TestLog::EndSection;
114
115			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if the reserved buffer object name 0 is bound to target.");
116			glBindBuffer(GL_ARRAY_BUFFER, 0);
117			glBufferSubData(GL_ARRAY_BUFFER, 1, 1, 0);
118			expectError(GL_INVALID_OPERATION);
119			m_log << TestLog::EndSection;
120
121			glDeleteBuffers(1, &buffer);
122		});
123	ES2F_ADD_API_CASE(buffer_sub_data_size_offset, "Invalid glBufferSubData() usage",
124		{
125			GLuint buffer;
126			glGenBuffers(1, &buffer);
127			glBindBuffer(GL_ARRAY_BUFFER, buffer);
128			glBufferData(GL_ARRAY_BUFFER, 10, 0, GL_STREAM_DRAW);
129
130			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if offset or size is negative, or if together they define a region of memory that extends beyond the buffer object's allocated data store.");
131			glBufferSubData(GL_ARRAY_BUFFER, -1, 1, 0);
132			expectError(GL_INVALID_VALUE);
133			glBufferSubData(GL_ARRAY_BUFFER, -1, -1, 0);
134			expectError(GL_INVALID_VALUE);
135			glBufferSubData(GL_ARRAY_BUFFER, 1, -1, 0);
136			expectError(GL_INVALID_VALUE);
137			glBufferSubData(GL_ARRAY_BUFFER, 15, 1, 0);
138			expectError(GL_INVALID_VALUE);
139			glBufferSubData(GL_ARRAY_BUFFER, 1, 15, 0);
140			expectError(GL_INVALID_VALUE);
141			glBufferSubData(GL_ARRAY_BUFFER, 8, 8, 0);
142			expectError(GL_INVALID_VALUE);
143			m_log << TestLog::EndSection;
144
145			glDeleteBuffers(1, &buffer);
146		});
147	ES2F_ADD_API_CASE(clear, "Invalid glClear() usage",
148		{
149			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if any bit other than the three defined bits is set in mask.");
150			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
151			expectError(GL_NO_ERROR);
152			glClear(0x00000200);
153			expectError(GL_INVALID_VALUE);
154			glClear(0x00001000);
155			expectError(GL_INVALID_VALUE);
156			glClear(0x00000010);
157			expectError(GL_INVALID_VALUE);
158			m_log << TestLog::EndSection;
159		});
160	ES2F_ADD_API_CASE(read_pixels, "Invalid glReadPixels() usage",
161		{
162			std::vector<GLubyte> ubyteData(4);
163
164			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if the combination of format and type is unsupported.");
165			glReadPixels(0, 0, 1, 1, GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT_4_4_4_4, &ubyteData[0]);
166			expectError(GL_INVALID_OPERATION);
167			m_log << TestLog::EndSection;
168
169			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if either width or height is negative.");
170			glReadPixels(0, 0, -1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &ubyteData[0]);
171			expectError(GL_INVALID_VALUE);
172			glReadPixels(0, 0, 1, -1, GL_RGBA, GL_UNSIGNED_BYTE, &ubyteData[0]);
173			expectError(GL_INVALID_VALUE);
174			glReadPixels(0, 0, -1, -1, GL_RGBA, GL_UNSIGNED_BYTE, &ubyteData[0]);
175			expectError(GL_INVALID_VALUE);
176			m_log << TestLog::EndSection;
177
178			m_log << TestLog::Section("", "GL_INVALID_FRAMEBUFFER_OPERATION is generated if the currently bound framebuffer is not framebuffer complete.");
179			GLuint fbo;
180			glGenFramebuffers(1, &fbo);
181			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
182			glCheckFramebufferStatus(GL_FRAMEBUFFER);
183			glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &ubyteData[0]);
184			expectError(GL_INVALID_FRAMEBUFFER_OPERATION);
185			m_log << TestLog::EndSection;
186		});
187	ES2F_ADD_API_CASE(read_pixels_format_mismatch, "Invalid glReadPixels() usage",
188		{
189			std::vector<GLubyte> ubyteData(4);
190			std::vector<GLushort> ushortData(4);
191
192			m_log << TestLog::Section("", "Unsupported combinations of format and type will generate an INVALID_OPERATION error.");
193			glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_SHORT_5_6_5, &ushortData[0]);
194			expectError(GL_INVALID_OPERATION);
195			glReadPixels(0, 0, 1, 1, GL_ALPHA, GL_UNSIGNED_SHORT_5_6_5, &ushortData[0]);
196			expectError(GL_INVALID_OPERATION);
197			glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_SHORT_4_4_4_4, &ushortData[0]);
198			expectError(GL_INVALID_OPERATION);
199			glReadPixels(0, 0, 1, 1, GL_ALPHA, GL_UNSIGNED_SHORT_4_4_4_4, &ushortData[0]);
200			expectError(GL_INVALID_OPERATION);
201			glReadPixels(0, 0, 1, 1, GL_RGB, GL_UNSIGNED_SHORT_5_5_5_1, &ushortData[0]);
202			expectError(GL_INVALID_OPERATION);
203			glReadPixels(0, 0, 1, 1, GL_ALPHA, GL_UNSIGNED_SHORT_5_5_5_1, &ushortData[0]);
204			expectError(GL_INVALID_OPERATION);
205			m_log << TestLog::EndSection;
206
207			m_log << TestLog::Section("", "GL_RGBA/GL_UNSIGNED_BYTE is always accepted and the other acceptable pair can be discovered by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE.");
208			glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &ubyteData[0]);
209			expectError(GL_NO_ERROR);
210			GLint readFormat;
211			GLint readType;
212			glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat);
213			glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &readType);
214			glReadPixels(0, 0, 1, 1, readFormat, readType, &ubyteData[0]);
215			expectError(GL_NO_ERROR);
216			m_log << TestLog::EndSection;
217		});
218
219	// Framebuffer Objects
220
221	ES2F_ADD_API_CASE(bind_framebuffer, "Invalid glBindFramebuffer() usage",
222		{
223			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if target is not GL_FRAMEBUFFER.");
224			glBindFramebuffer(-1, 0);
225			expectError(GL_INVALID_ENUM);
226			glBindFramebuffer(GL_RENDERBUFFER, 0);
227			expectError(GL_INVALID_ENUM);
228			m_log << TestLog::EndSection;
229		});
230	ES2F_ADD_API_CASE(bind_renderbuffer, "Invalid glBindRenderbuffer() usage",
231		{
232			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if target is not GL_RENDERBUFFER.");
233			glBindRenderbuffer(-1, 0);
234			expectError(GL_INVALID_ENUM);
235			glBindRenderbuffer(GL_FRAMEBUFFER, 0);
236			expectError(GL_INVALID_ENUM);
237			m_log << TestLog::EndSection;
238		});
239	ES2F_ADD_API_CASE(check_framebuffer_status, "Invalid glCheckFramebufferStatus() usage",
240		{
241			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if target is not GL_FRAMEBUFFER.");
242			glCheckFramebufferStatus(-1);
243			expectError(GL_INVALID_ENUM);
244			glCheckFramebufferStatus(GL_RENDERBUFFER);
245			expectError(GL_INVALID_ENUM);
246			m_log << TestLog::EndSection;
247		});
248	ES2F_ADD_API_CASE(gen_framebuffers, "Invalid glGenFramebuffers() usage",
249		{
250			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if n is negative.");
251			glGenFramebuffers(-1, 0);
252			expectError(GL_INVALID_VALUE);
253			m_log << TestLog::EndSection;
254		});
255	ES2F_ADD_API_CASE(gen_renderbuffers, "Invalid glGenRenderbuffers() usage",
256		{
257			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if n is negative.");
258			glGenRenderbuffers(-1, 0);
259			expectError(GL_INVALID_VALUE);
260			m_log << TestLog::EndSection;
261		});
262	ES2F_ADD_API_CASE(delete_framebuffers, "Invalid glDeleteFramebuffers() usage",
263		{
264			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if n is negative.");
265			glDeleteFramebuffers(-1, 0);
266			expectError(GL_INVALID_VALUE);
267			m_log << TestLog::EndSection;
268		});
269	ES2F_ADD_API_CASE(delete_renderbuffers, "Invalid glDeleteRenderbuffers() usage",
270		{;
271			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if n is negative.");
272			glDeleteRenderbuffers(-1, 0);
273			expectError(GL_INVALID_VALUE);
274			m_log << TestLog::EndSection;
275		});
276	ES2F_ADD_API_CASE(framebuffer_renderbuffer, "Invalid glFramebufferRenderbuffer() usage",
277		{
278			GLuint fbo;
279			GLuint rbo;
280			glGenFramebuffers(1, &fbo);
281			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
282			glGenRenderbuffers(1, &rbo);
283
284			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if target is not GL_FRAMEBUFFER.");
285			glFramebufferRenderbuffer(-1, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
286			expectError(GL_INVALID_ENUM);
287			m_log << TestLog::EndSection;
288
289			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if attachment is not an accepted attachment point.");
290			glFramebufferRenderbuffer(GL_FRAMEBUFFER, -1, GL_RENDERBUFFER, 0);
291			expectError(GL_INVALID_ENUM);
292			m_log << TestLog::EndSection;
293
294			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if renderbuffertarget is not GL_RENDERBUFFER.");
295			glBindRenderbuffer(GL_RENDERBUFFER, rbo);
296			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, -1, rbo);
297			expectError(GL_INVALID_ENUM);
298			glBindRenderbuffer(GL_RENDERBUFFER, 0);
299			m_log << TestLog::EndSection;
300
301			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if renderbuffer is neither 0 nor the name of an existing renderbuffer object.");
302			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, -1);
303			expectError(GL_INVALID_OPERATION);
304			m_log << TestLog::EndSection;
305
306			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if the default framebuffer object name 0 is bound.");
307			glBindFramebuffer(GL_FRAMEBUFFER, 0);
308			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
309			expectError(GL_INVALID_OPERATION);
310			m_log << TestLog::EndSection;
311
312			glDeleteRenderbuffers(1, &rbo);
313			glDeleteFramebuffers(1, &fbo);
314		});
315	ES2F_ADD_API_CASE(framebuffer_texture2d, "Invalid glFramebufferTexture2D() usage",
316		{
317			GLuint fbo;
318			GLuint tex2D;
319			GLuint texCube;
320			glGenFramebuffers(1, &fbo);
321			glBindFramebuffer(GL_FRAMEBUFFER, fbo);
322			glGenTextures(1, &tex2D);
323			glBindTexture(GL_TEXTURE_2D, tex2D);
324			glGenTextures(1, &texCube);
325			glBindTexture(GL_TEXTURE_CUBE_MAP, texCube);
326			expectError(GL_NO_ERROR);
327
328			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if target is not GL_FRAMEBUFFER.");
329			glFramebufferTexture2D(-1, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
330			expectError(GL_INVALID_ENUM);
331			m_log << TestLog::EndSection;
332
333			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if textarget is not an accepted texture target.");
334			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, -1, tex2D, 0);
335			expectError(GL_INVALID_ENUM);
336			m_log << TestLog::EndSection;
337
338			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if attachment is not an accepted attachment point.");
339			glFramebufferTexture2D(GL_FRAMEBUFFER, -1, GL_TEXTURE_2D, 0, 0);
340			expectError(GL_INVALID_ENUM);
341			m_log << TestLog::EndSection;
342
343			if (!m_context.getContextInfo().isExtensionSupported("GL_OES_fbo_render_mipmap"))
344			{
345				m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if level is not 0.");
346				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2D, 3);
347				expectError(GL_INVALID_VALUE);
348				m_log << TestLog::EndSection;
349			}
350
351			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if texture is neither 0 nor the name of an existing texture object.");
352			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, -1, 0);
353			expectError(GL_INVALID_OPERATION);
354			m_log << TestLog::EndSection;
355
356			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if texture is the name of an existing two-dimensional texture object but textarget is not GL_TEXTURE_2D.");
357
358			expectError(GL_NO_ERROR);
359			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, tex2D, 0);
360			expectError(GL_INVALID_OPERATION);
361			glDeleteTextures(1, &tex2D);
362			m_log << TestLog::EndSection;
363
364			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if texture is the name of an existing cube map texture object but textarget is GL_TEXTURE_2D.");
365			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texCube, 0);
366			expectError(GL_INVALID_OPERATION);
367			glDeleteTextures(1, &texCube);
368			m_log << TestLog::EndSection;
369
370			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if the default framebuffer object name 0 is bound.");
371			glBindFramebuffer(GL_FRAMEBUFFER, 0);
372			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
373			expectError(GL_INVALID_OPERATION);
374			m_log << TestLog::EndSection;
375
376			glDeleteFramebuffers(1, &fbo);
377		});
378	ES2F_ADD_API_CASE(renderbuffer_storage, "Invalid glRenderbufferStorage() usage",
379		{
380			GLuint rbo;
381			glGenRenderbuffers(1, &rbo);
382			glBindRenderbuffer(GL_RENDERBUFFER, rbo);
383
384			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if target is not GL_RENDERBUFFER.");
385			glRenderbufferStorage(-1, GL_RGBA4, 1, 1);
386			expectError(GL_INVALID_ENUM);
387			glRenderbufferStorage(GL_FRAMEBUFFER, GL_RGBA4, 1, 1);
388			expectError(GL_INVALID_ENUM);
389			m_log << TestLog::EndSection;
390
391			m_log << TestLog::Section("", "GL_INVALID_ENUM is generated if internalformat is not an accepted format.");
392			glRenderbufferStorage(GL_RENDERBUFFER, -1, 1, 1);
393			expectError(GL_INVALID_ENUM);
394			glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, 1, 1);
395			expectError(GL_INVALID_ENUM);
396			m_log << TestLog::EndSection;
397
398			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if width or height is less than zero.");
399			glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, -1, 1);
400			expectError(GL_INVALID_VALUE);
401			glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 1, -1);
402			expectError(GL_INVALID_VALUE);
403			glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, -1, -1);
404			expectError(GL_INVALID_VALUE);
405			m_log << TestLog::EndSection;
406
407			m_log << TestLog::Section("", "GL_INVALID_VALUE is generated if width or height is greater than GL_MAX_RENDERBUFFER_SIZE.");
408			GLint maxSize;
409			glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxSize);
410			glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 1, maxSize+1);
411			expectError(GL_INVALID_VALUE);
412			glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, maxSize+1, 1);
413			expectError(GL_INVALID_VALUE);
414			glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, maxSize+1, maxSize+1);
415			expectError(GL_INVALID_VALUE);
416			m_log << TestLog::EndSection;
417
418			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if the reserved renderbuffer object name 0 is bound.");
419			glBindRenderbuffer(GL_RENDERBUFFER, 0);
420			glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 1, 1);
421			expectError(GL_INVALID_OPERATION);
422			m_log << TestLog::EndSection;
423
424			glDeleteRenderbuffers(1, &rbo);
425		});
426}
427
428} // Functional
429} // gles2
430} // deqp
431