1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.renderscript.cts;
18 
19 import android.renderscript.Allocation;
20 import android.renderscript.Element;
21 import android.renderscript.RenderScript;
22 import android.renderscript.RenderScript.RSErrorHandler;
23 import android.renderscript.RSRuntimeException;
24 import android.renderscript.Type;
25 import android.util.Log;
26 import java.util.Random;
27 import java.util.function.*;
28 
29 public class DebugContext extends RSBaseCompute {
30     Allocation AUnused;
31     Allocation AInt;
32     ScriptC_oob Soob;
33 
34     boolean mRanErrorHandler = false;
35     RSErrorHandler mRsError = new RSErrorHandler() {
36         public void run() {
37             mRanErrorHandler = true;
38             Log.e("RenderscriptCTS", mErrorMessage);
39         }
40     };
41 
setupDebugContext()42     protected void setupDebugContext() {
43         mRS.destroy();
44         mRS = RenderScript.create(mCtx, RenderScript.ContextType.DEBUG);
45         mRS.setMessageHandler(mRsMessage);
46         mRS.setErrorHandler(mRsError);
47 
48         Soob = new ScriptC_oob(mRS);
49 
50         Type.Builder typeBuilder = new Type.Builder(mRS, Element.I32(mRS));
51         Type t = typeBuilder.setX(1).create();
52 
53         AInt = Allocation.createTyped(mRS, t);
54         Soob.set_aInt(AInt);
55 
56         AUnused = Allocation.createTyped(mRS, t);
57     }
58 
59     /**
60      * Test whether we are detect out-of-bounds allocation accesses
61      * from an invokable.
62      */
testDebugContextI()63     public void testDebugContextI() {
64         setupDebugContext();
65         Soob.invoke_write_i(7, 1);  // Write to invalid location.
66 
67         // Flush messages through the pipeline.
68         mRS.sendMessage(RS_MSG_TEST_FLUSH, null);
69         waitForMessage();
70 
71         Soob.destroy();
72         assertTrue(mRanErrorHandler);
73 
74         // The context is dead at this point so make sure it's not reused
75         RenderScript.releaseAllContexts();
76     }
77 
78     /**
79      * Test whether we are detect out-of-bounds allocation accesses
80      * from a kernel.
81      */
testDebugContextK()82     public void testDebugContextK() {
83         setupDebugContext();
84         Soob.forEach_write_k(AUnused);  // Write to invalid location.
85 
86         // Flush messages through the pipeline.
87         mRS.sendMessage(RS_MSG_TEST_FLUSH, null);
88         waitForMessage();
89 
90         Soob.destroy();
91         assertTrue(mRanErrorHandler);
92 
93         // The context is dead at this point so make sure it's not reused
94         RenderScript.releaseAllContexts();
95     }
96 
97     /**
98      * Helper for rsAllocationCopy tests
99      */
100 
101     protected class SetupAllocationCopyTests {
102         int Width;
103         int Height;
104         int ArrLen;
105         Allocation aIn;
106         Allocation aOut;
107         Random RN;
108 
SetupAllocationCopyTests(int dimension, int size, Function<RenderScript, Type.Builder> TB, long seed)109         SetupAllocationCopyTests(int dimension,
110             int size, Function<RenderScript, Type.Builder> TB, long seed) {
111             // Type.Builder constructor needs a RenderScript instance,
112             // and that's created by setupDebugContext(). Hence a
113             // Function<RenderScript, Type.Builder> is needed here
114 
115             assertTrue(dimension == 1 || dimension == 2);
116 
117             setupDebugContext();
118             RN = new Random(seed);
119             // So that we can have offsets that will be invalid in another
120             // dimension
121             Width = RN.nextInt(size/2)+size/2;
122             Height = RN.nextInt(size/2);
123             if (dimension == 1) {
124                 ArrLen = Width;
125             } else {
126                 ArrLen = Width * Height;
127             }
128 
129             Type.Builder typeBuilder = TB.apply(mRS);
130 
131             if (dimension == 1)
132                 typeBuilder.setX(Width);
133             else
134                 typeBuilder.setX(Width).setY(Height);
135 
136             aIn = Allocation.createTyped(mRS, typeBuilder.create());
137             aOut = Allocation.createTyped(mRS, typeBuilder.create());
138 
139             // Initialize test Allocations
140             if (aIn.getElement().getDataType() == Element.DataType.SIGNED_8) {
141                 byte[] inArray = new byte[ArrLen];
142                 RN.nextBytes(inArray);
143                 byte[] outArray = new byte[ArrLen];
144                 aIn.copyFrom(inArray);
145                 aOut.copyFrom(outArray);
146             } else {
147                 assertTrue(aIn.getElement().getDataType() ==
148                     Element.DataType.SIGNED_16);
149                 short[] inArray = new short[ArrLen];
150                 for (int i = 0; i < ArrLen; i++)
151                    inArray[i] = (short)RN.nextInt();
152                 short[] outArray = new short[ArrLen];
153                 aIn.copyFrom(inArray);
154                 aOut.copyFrom(outArray);
155             }
156 
157             // Setup script environment
158             if (dimension == 1) {
159                 Soob.set_aIn1D(aIn);
160                 Soob.set_aOut1D(aOut);
161             } else {
162                 Soob.set_aIn2D(aIn);
163                 Soob.set_aOut2D(aOut);
164             }
165         }
166 
finishAllocationCopyTests()167         protected void finishAllocationCopyTests() {
168             mRS.finish();
169 
170             // Flush messages through the pipeline.
171             mRS.sendMessage(RS_MSG_TEST_FLUSH, null);
172             waitForMessage();
173             Soob.destroy();
174         }
175     }
176 
177     /**
178      * 1D copy - things should work under DebugContext if given
179      * legitimate arguments
180      */
testDebugContextRsAllocationCopy1D_Byte_Normal()181     public void testDebugContextRsAllocationCopy1D_Byte_Normal() {
182         SetupAllocationCopyTests AC =
183             new SetupAllocationCopyTests(1, 512,
184                 (RenderScript rs)-> new Type.Builder(rs, Element.I8(rs)),
185                 0x172d8ab9);
186         int Offset = AC.RN.nextInt(AC.Width);
187         int Count = AC.RN.nextInt(AC.Width - Offset);
188         Soob.set_dstXOff(Offset);
189         Soob.set_srcXOff(Offset);
190         Soob.set_xCount(Count);
191         Soob.set_srcMip(0);
192         Soob.set_dstMip(0);
193         Soob.invoke_test1D();
194 
195         AC.finishAllocationCopyTests();
196 
197         // Validate results
198         boolean result = true;
199         byte[] inArray = new byte[AC.ArrLen];
200         byte[] outArray = new byte[AC.ArrLen];
201         AC.aIn.copyTo(inArray);
202         AC.aOut.copyTo(outArray);
203         for (int i = 0; i < AC.Width; i++) {
204             if (Offset <= i && i < Offset + Count) {
205                 if (inArray[i] != outArray[i]) {
206                     result = false;
207                     break;
208                 }
209             } else {
210                 if (outArray[i] != 0) {
211                     result = false;
212                     break;
213                 }
214             }
215         }
216         assertTrue(result);
217 
218         RenderScript.releaseAllContexts();
219     }
220 
221     /**
222      * 2D copy - with legitimate arguments
223      */
testDebugContextRsAllocationCopy2D_Short_Normal()224     public void testDebugContextRsAllocationCopy2D_Short_Normal() {
225         SetupAllocationCopyTests AC =
226             new SetupAllocationCopyTests(2, 128,
227                 (RenderScript rs)-> new Type.Builder(rs, Element.I16(rs)),
228                 0x172d8aba);
229         // to make sure xOff is not a valid yOff.
230         int xOff = AC.RN.nextInt(AC.Width-AC.Height) + AC.Height;
231         int yOff = AC.RN.nextInt(AC.Height);
232         int xCount = AC.RN.nextInt(AC.Width - xOff);
233         int yCount = AC.RN.nextInt(AC.Height - yOff);
234 
235         Soob.set_dstXOff(xOff);
236         Soob.set_srcXOff(xOff);
237         Soob.set_yOff(yOff);
238         Soob.set_xCount(xCount);
239         Soob.set_yCount(yCount);
240         Soob.set_srcMip(0);
241         Soob.set_dstMip(0);
242         Soob.invoke_test2D();
243 
244         AC.finishAllocationCopyTests();
245 
246         // Validate results
247         boolean result = true;
248         short[] inArray = new short[AC.ArrLen];
249         short[] outArray = new short[AC.ArrLen];
250         AC.aIn.copyTo(inArray);
251         AC.aOut.copyTo(outArray);
252         for (int i = 0; i < AC.Height; i++) {
253             for (int j = 0; j < AC.Width; j++) {
254                 int pos = i * AC.Width + j;
255                 if (yOff <= i && i < yOff + yCount &&
256                     xOff <= j && j < xOff + xCount) {
257                     if (inArray[pos] != outArray[pos]) {
258                         result = false;
259                         break;
260                     }
261                 } else {
262                     if (outArray[pos] != 0) {
263                        result = false;
264                        break;
265                     }
266                 }
267             }
268         }
269         assertTrue(result);
270 
271         // The context is dead at this point so make sure it's not reused
272         RenderScript.releaseAllContexts();
273     }
274 
275     /**
276      * Test invalid arguments to rsAllocationCopy1D - bad source LOD
277      */
testDebugContextRsAllocationCopy1D_Byte_BadSrcLOD()278     public void testDebugContextRsAllocationCopy1D_Byte_BadSrcLOD() {
279         SetupAllocationCopyTests AC =
280             new SetupAllocationCopyTests(1, 512,
281                 (RenderScript rs)-> new Type.Builder(rs, Element.I8(rs)),
282                 0x172d8abb);
283         int Offset = AC.RN.nextInt(AC.Width);
284         int Count = AC.RN.nextInt(AC.Width - Offset);
285         Soob.set_dstXOff(Offset);
286         Soob.set_srcXOff(Offset);
287         Soob.set_xCount(Count);
288         Soob.set_srcMip(1);  // bad source LOD
289         Soob.set_dstMip(0);
290         Soob.invoke_test1D();
291 
292         AC.finishAllocationCopyTests();
293         assertTrue(mRanErrorHandler);
294 
295         // The context is dead at this point so make sure it's not reused
296         RenderScript.releaseAllContexts();
297     }
298 
299     /**
300      * Test invalid arguments to rsAllocationCopy1D - bad destination LOD
301      */
testDebugContextRsAllocationCopy1D_Byte_BadDstLOD()302     public void testDebugContextRsAllocationCopy1D_Byte_BadDstLOD() {
303         SetupAllocationCopyTests AC =
304             new SetupAllocationCopyTests(1, 512,
305                 (RenderScript rs)-> new Type.Builder(rs, Element.I8(rs)),
306                 0x172d8abc);
307         int Offset = AC.RN.nextInt(AC.Width);
308         int Count = AC.RN.nextInt(AC.Width - Offset);
309         Soob.set_dstXOff(Offset);
310         Soob.set_srcXOff(Offset);
311         Soob.set_xCount(Count);
312         Soob.set_srcMip(0);
313         Soob.set_dstMip(1);  // bad destination LOD
314         Soob.invoke_test1D();
315 
316         AC.finishAllocationCopyTests();
317         assertTrue(mRanErrorHandler);
318 
319         // The context is dead at this point so make sure it's not reused
320         RenderScript.releaseAllContexts();
321     }
322 
323 
324     /**
325      * Test invalid arguments to rsAllocationCopy1D - invalid count
326      */
testDebugContextRsAllocationCopy1D_Byte_BadCount()327     public void testDebugContextRsAllocationCopy1D_Byte_BadCount() {
328         SetupAllocationCopyTests AC =
329             new SetupAllocationCopyTests(1, 512,
330                 (RenderScript rs)-> new Type.Builder(rs, Element.I8(rs)),
331                 0x172d8abd);
332         int Offset = AC.RN.nextInt(AC.Width);
333         Soob.set_dstXOff(Offset);
334         Soob.set_srcXOff(Offset);
335         Soob.set_xCount(AC.Width - Offset + 1);  // Invalid count by 1
336         Soob.set_srcMip(0);
337         Soob.set_dstMip(0);
338         Soob.invoke_test1D();
339 
340         AC.finishAllocationCopyTests();
341         assertTrue(mRanErrorHandler);
342 
343         // The context is dead at this point so make sure it's not reused
344         RenderScript.releaseAllContexts();
345     }
346 
347     /**
348      * Test invalid arguments to rsAllocationCopy1D - invalid source offset
349      */
testDebugContextRsAllocationCopy1D_Byte_BadSrcOffset()350     public void testDebugContextRsAllocationCopy1D_Byte_BadSrcOffset() {
351         SetupAllocationCopyTests AC =
352             new SetupAllocationCopyTests(1, 512,
353                 (RenderScript rs)-> new Type.Builder(rs, Element.I8(rs)),
354                 0x172d8abe);
355 
356         int Offset = AC.RN.nextInt(AC.Width);
357         Soob.set_dstXOff(Offset);
358         Soob.set_srcXOff(AC.Width);  // Invalid src offset
359         Soob.set_xCount(1);
360         Soob.set_srcMip(0);
361         Soob.set_dstMip(0);
362         Soob.invoke_test1D();
363 
364         AC.finishAllocationCopyTests();
365         assertTrue(mRanErrorHandler);
366 
367         // The context is dead at this point so make sure it's not reused
368         RenderScript.releaseAllContexts();
369     }
370 
371     /**
372      * Test invalid arguments to rsAllocationCopy1D - invalid destination offset
373      */
testDebugContextRsAllocationCopy1D_Byte_BadDstOffset()374     public void testDebugContextRsAllocationCopy1D_Byte_BadDstOffset() {
375         SetupAllocationCopyTests AC =
376             new SetupAllocationCopyTests(1, 512,
377                 (RenderScript rs)-> new Type.Builder(rs, Element.I8(rs)),
378                 0x172d8abf);
379 
380         int Offset = AC.RN.nextInt(AC.Width);
381         Soob.set_dstXOff(AC.ArrLen);  // Invalid dst offset
382         Soob.set_srcXOff(Offset);  // Invalid src offset
383         Soob.set_xCount(1);
384         Soob.set_srcMip(0);
385         Soob.set_dstMip(0);
386         Soob.invoke_test1D();
387 
388         AC.finishAllocationCopyTests();
389         assertTrue(mRanErrorHandler);
390 
391         // The context is dead at this point so make sure it's not reused
392         RenderScript.releaseAllContexts();
393     }
394 
395 
396     /**
397      * Test invalid arguments to rsAllocationCopy2D - invalid y count
398      */
testDebugContextRsAllocationCopy2D_Short_BadYCount()399     public void testDebugContextRsAllocationCopy2D_Short_BadYCount() {
400         SetupAllocationCopyTests AC =
401             new SetupAllocationCopyTests(2, 128,
402                 (RenderScript rs)-> new Type.Builder(rs, Element.I16(rs)),
403                 0x172d8ac0);
404         int xOff = AC.RN.nextInt(AC.Width);
405         int yOff = AC.RN.nextInt(AC.Height);
406         int xCount = AC.RN.nextInt(AC.Width - xOff);
407 
408         Soob.set_dstXOff(xOff);
409         Soob.set_srcXOff(xOff);
410         Soob.set_yOff(yOff);
411         Soob.set_xCount(xCount);  // Legitimate X count
412         Soob.set_yCount(AC.Height - yOff + 1);  // Invalid Y count by 1
413         Soob.set_srcMip(0);
414         Soob.set_dstMip(0);
415         Soob.invoke_test2D();
416 
417         AC.finishAllocationCopyTests();
418         assertTrue(mRanErrorHandler);
419 
420         // The context is dead at this point so make sure it's not reused
421         RenderScript.releaseAllContexts();
422     }
423 
424     /**
425      * Test invalid arguments to rsAllocationCopy2D - 2D operation on
426      * an 1D Allocation
427      */
testDebugContextRsAllocationCopy2D_Short_WrongD()428     public void testDebugContextRsAllocationCopy2D_Short_WrongD() {
429         setupDebugContext();
430 
431         Random random = new Random(0x172d8ac1);
432         int width = random.nextInt(128);
433         int height = random.nextInt(128);
434         int xOff = random.nextInt(width);
435         int yOff = random.nextInt(height);
436         int xCount = random.nextInt(width - xOff);
437         int yCount = random.nextInt(height - yOff);
438         int arr_len = width * height;
439 
440 
441         Type.Builder typeBuilder1 = new Type.Builder(mRS, Element.I16(mRS));
442         typeBuilder1.setX(width);
443         // aIn is one-dimensional
444         Allocation aIn = Allocation.createTyped(mRS, typeBuilder1.create());
445         Type.Builder typeBuilder2 = new Type.Builder(mRS, Element.I16(mRS));
446         typeBuilder2.setX(width).setY(height);
447         Allocation aOut = Allocation.createTyped(mRS, typeBuilder2.create());
448 
449         Soob.set_aIn2D(aIn);
450         Soob.set_aOut2D(aOut);
451         Soob.set_srcXOff(xOff);
452         Soob.set_dstXOff(xOff);
453         Soob.set_yOff(yOff);
454         Soob.set_xCount(xCount);  // Legitimate X count
455         Soob.set_yCount(yCount);  // Legitimate Y count (w.r.t aOut)
456         Soob.set_srcMip(0);
457         Soob.set_dstMip(0);
458         Soob.invoke_test2D();
459         mRS.finish();
460 
461         // Flush messages through the pipeline.
462         mRS.sendMessage(RS_MSG_TEST_FLUSH, null);
463         waitForMessage();
464 
465         Soob.destroy();
466         assertTrue(mRanErrorHandler);
467 
468         // The context is dead at this point so make sure it's not reused
469         RenderScript.releaseAllContexts();
470     }
471 
472 
473 }
474