1 /*
2  * Copyright (C) 2016 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 #include "shared.rsh"
18 
19 // Ensure that we can reflect correct Java code for a struct with
20 // multiple fields of type struct.  Java sets the script global
21 // variable "outer", and then calls a verification invokable
22 // "checkOuter()", passing the expected field values as scalar
23 // arguments.
24 
25 struct InnerOne {
26     int x;
27     int y;
28     float f;
29 };
30 
31 typedef struct InnerOne s_innerOne;
32 
33 struct InnerTwo {
34     int8_t z;
35     struct InnerOne innerOne;
36 };
37 
38 struct Outer {
39     struct InnerOne innerOneA;
40     long l;  // to induce padding
41     struct InnerOne innerOneB;
42     struct InnerTwo innerTwo3[3];
43     struct InnerTwo innerTwo2[2];
44     struct InnerOne innerOne4[4];
45     s_innerOne      innerOneC;  // does a typedef confuse reflection?
46 };
47 
48 struct Outer outer;
49 
50 // Fragment of incoming argument list: Fields for struct InnerOne.
51 // Arguments are named argPrefix"_x", argPrefix"_y", argPrefix"_f".
52 #define ARGS_INNERONE_(argPrefix) \
53     int argPrefix ## _x, int argPrefix ## _y, float argPrefix ## _f
54 
55 // Fragment of incoming argument list: Fields for struct InnerOne
56 // within struct Outer.
57 // Arguments are named outerFieldName"_x", outerFieldName"_y", outerFieldName"_f".
58 #define ARGS_INNERONE_SCALAR(outerFieldName) \
59     ARGS_INNERONE_(outerFieldName)
60 
61 // Fragment of incoming argument list: Fields for element of array of
62 // struct InnerOne within struct Outer.
63 // Arguments are named outerFieldName"_"index"_x", outerFieldName"_"index"_y",
64 // and outerFieldName"_"index"_f".
65 #define ARGS_INNERONE_ARRAY(outerFieldName, index) \
66     ARGS_INNERONE_(outerFieldName ## _ ## index)
67 
68 // Fragment of incoming argument list: Fields for element of array of
69 // struct InnerTwo (with nested InnerOne flattened out) within struct Outer.
70 // Arguments are named outerFieldName"_"index"_z", outerFieldName"_"index"_innerOne_x", etc.
71 #define ARGS_INNERTWO_ARRAY(outerFieldName, index) \
72     int8_t outerFieldName ## _ ## index ## _z, ARGS_INNERONE_(outerFieldName ## _ ## index ## _innerOne)
73 
74 // #define TRACE(...) rsDebug(__VA_ARGS__)
75 #define TRACE(...) (void)0
76 
77 void checkOuter(ARGS_INNERONE_SCALAR(innerOneA),
78                 long l,
79                 ARGS_INNERONE_SCALAR(innerOneB),
80                 ARGS_INNERTWO_ARRAY(innerTwo3, 0),
81                 ARGS_INNERTWO_ARRAY(innerTwo3, 1),
82                 ARGS_INNERTWO_ARRAY(innerTwo3, 2),
83                 ARGS_INNERTWO_ARRAY(innerTwo2, 0),
84                 ARGS_INNERTWO_ARRAY(innerTwo2, 1),
85                 ARGS_INNERONE_ARRAY(innerOne4, 0),
86                 ARGS_INNERONE_ARRAY(innerOne4, 1),
87                 ARGS_INNERONE_ARRAY(innerOne4, 2),
88                 ARGS_INNERONE_ARRAY(innerOne4, 3),
89                 ARGS_INNERONE_SCALAR(innerOneC)) {
90     bool failed = false;
91 
92     // Compare contents of a struct InnerOne instance against incoming argument values.
93     // Compares instanceName".x" to argPrefix"_x", etc.
94 #define CHECK_INNERONE_(instanceName, argPrefix)       \
95     do {                                               \
96        TRACE(# instanceName, instanceName.x);          \
97         _RS_ASSERT(instanceName.x == argPrefix ## _x); \
98        TRACE(# instanceName, instanceName.y);          \
99         _RS_ASSERT(instanceName.y == argPrefix ## _y); \
100        TRACE(# instanceName, instanceName.f);          \
101         _RS_ASSERT(instanceName.f == argPrefix ## _f); \
102     } while(false)
103 
104     // Compare contents of a struct InnerOne instance within global
105     // variable "outer" against incoming argument values.
106     // Compares "outer."outerFieldName".x" to outerFieldName"_x", etc.
107 #define CHECK_INNERONE_SCALAR(outerFieldName) \
108     CHECK_INNERONE_(outer.outerFieldName, outerFieldName)
109 
110     // Compare contents of element of array of struct InnerOne
111     // instance within global variable "outer" against incoming argument values.
112     // Compares "outer"outerFieldName"["index"].x" to outerFieldName"_"index"_x", etc.
113 #define CHECK_INNERONE_ARRAY(outerFieldName, index) \
114     CHECK_INNERONE_(outer.outerFieldName[index], outerFieldName ## _ ## index)
115 
116     // Compare contents of element of array of struct InnerTwo
117     // instance within global variable "outer" against incoming argument values.
118     // Compares "outer."outerFieldName"["index"].z" to outerFieldName"_"index"_z",
119     // "outer."outerFieldName"["index"].innerOne.x" to outerFieldName""index"_innerOne_x",
120     // etc.
121 #define CHECK_INNERTWO_ARRAY(outerFieldName, index)                                                 \
122     do {                                                                                            \
123         TRACE(# index, outer.outerFieldName[index].z);                \
124         _RS_ASSERT(outer.outerFieldName[index].z == outerFieldName ## _ ## index ## _z); \
125         CHECK_INNERONE_(outer.outerFieldName[index].innerOne, outerFieldName ## _ ## index ## _innerOne); \
126     } while (false);
127 
128     CHECK_INNERONE_SCALAR(innerOneA);
129     TRACE("l", outer.l);
130     _RS_ASSERT(outer.l == l);
131     CHECK_INNERONE_SCALAR(innerOneB);
132     CHECK_INNERTWO_ARRAY(innerTwo3, 0);
133     CHECK_INNERTWO_ARRAY(innerTwo3, 1);
134     CHECK_INNERTWO_ARRAY(innerTwo3, 2);
135     CHECK_INNERTWO_ARRAY(innerTwo2, 0);
136     CHECK_INNERTWO_ARRAY(innerTwo2, 1);
137     CHECK_INNERONE_ARRAY(innerOne4, 0);
138     CHECK_INNERONE_ARRAY(innerOne4, 1);
139     CHECK_INNERONE_ARRAY(innerOne4, 2);
140     CHECK_INNERONE_ARRAY(innerOne4, 3);
141     CHECK_INNERONE_SCALAR(innerOneC);
142 
143     if (failed) {
144         rsSendToClientBlocking(RS_MSG_TEST_FAILED);
145     }
146     else {
147         rsSendToClientBlocking(RS_MSG_TEST_PASSED);
148     }
149 }
150