Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2016 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkSLCompiler.h"
      9 
     10 #include "Test.h"
     11 
     12 #if SK_SUPPORT_GPU
     13 
     14 static void test_failure(skiatest::Reporter* r, const char* src, const char* error) {
     15     SkSL::Compiler compiler;
     16     SkSL::Program::Settings settings;
     17     sk_sp<GrShaderCaps> caps = SkSL::ShaderCapsFactory::Default();
     18     settings.fCaps = caps.get();
     19     compiler.convertProgram(SkSL::Program::kFragment_Kind, SkSL::String(src), settings);
     20     SkSL::String skError(error);
     21     if (compiler.errorText() != skError) {
     22         SkDebugf("SKSL ERROR:\n    source: %s\n    expected: %s    received: %s", src, error,
     23                  compiler.errorText().c_str());
     24     }
     25     REPORTER_ASSERT(r, compiler.errorText() == skError);
     26 }
     27 
     28 static void test_success(skiatest::Reporter* r, const char* src) {
     29     SkSL::Compiler compiler;
     30     SkSL::Program::Settings settings;
     31     sk_sp<GrShaderCaps> caps = SkSL::ShaderCapsFactory::Default();
     32     settings.fCaps = caps.get();
     33     std::unique_ptr<SkSL::Program> program = compiler.convertProgram(SkSL::Program::kFragment_Kind,
     34                                                                      SkSL::String(src), settings);
     35     REPORTER_ASSERT(r, program);
     36 }
     37 
     38 DEF_TEST(SkSLUndefinedSymbol, r) {
     39     test_failure(r,
     40                  "void main() { x = float2(1); }",
     41                  "error: 1: unknown identifier 'x'\n1 error\n");
     42 }
     43 
     44 DEF_TEST(SkSLUndefinedFunction, r) {
     45     test_failure(r,
     46                  "void main() { int x = foo(1); }",
     47                  "error: 1: unknown identifier 'foo'\n1 error\n");
     48 }
     49 
     50 DEF_TEST(SkSLGenericArgumentMismatch, r) {
     51     test_failure(r,
     52                  "void main() { float x = sin(1, 2); }",
     53                  "error: 1: call to 'sin' expected 1 argument, but found 2\n1 error\n");
     54     test_failure(r,
     55                  "void main() { float x = sin(true); }",
     56                  "error: 1: no match for sin(bool)\n1 error\n");
     57     test_success(r,
     58                  "void main() { float x = sin(1); }");
     59 }
     60 
     61 DEF_TEST(SkSLArgumentCountMismatch, r) {
     62     test_failure(r,
     63                  "float foo(float x) { return x * x; }"
     64                  "void main() { float x = foo(1, 2); }",
     65                  "error: 1: call to 'foo' expected 1 argument, but found 2\n1 error\n");
     66 }
     67 
     68 DEF_TEST(SkSLArgumentMismatch, r) {
     69     test_failure(r,
     70                  "float foo(float x) { return x * x; }"
     71                  "void main() { float x = foo(true); }",
     72                  "error: 1: expected 'float', but found 'bool'\n1 error\n");
     73 }
     74 
     75 DEF_TEST(SkSLIfTypeMismatch, r) {
     76     test_failure(r,
     77                  "void main() { if (3) { } }",
     78                  "error: 1: expected 'bool', but found 'int'\n1 error\n");
     79 }
     80 
     81 DEF_TEST(SkSLDoTypeMismatch, r) {
     82     test_failure(r,
     83                  "void main() { do { } while (float2(1)); }",
     84                  "error: 1: expected 'bool', but found 'float2'\n1 error\n");
     85 }
     86 
     87 DEF_TEST(SkSLWhileTypeMismatch, r) {
     88     test_failure(r,
     89                  "void main() { while (float3(1)) { } }",
     90                  "error: 1: expected 'bool', but found 'float3'\n1 error\n");
     91 }
     92 
     93 DEF_TEST(SkSLForTypeMismatch, r) {
     94     test_failure(r,
     95                  "void main() { for (int x = 0; x; x++) { } }",
     96                  "error: 1: expected 'bool', but found 'int'\n1 error\n");
     97 }
     98 
     99 DEF_TEST(SkSLConstructorTypeMismatch, r) {
    100     test_failure(r,
    101                  "void main() { float2 x = float2(1.0, false); }",
    102                  "error: 1: expected 'float', but found 'bool'\n1 error\n");
    103     test_failure(r,
    104                  "void main() { float2 x = float2(bool2(false)); }",
    105                  "error: 1: 'bool2' is not a valid parameter to 'float2' constructor\n1 error\n");
    106     test_failure(r,
    107                  "void main() { bool2 x = bool2(float2(1)); }",
    108                  "error: 1: 'float2' is not a valid parameter to 'bool2' constructor\n1 error\n");
    109     test_failure(r,
    110                  "void main() { bool x = bool(1.0); }",
    111                  "error: 1: cannot construct 'bool'\n1 error\n");
    112     test_failure(r,
    113                  "struct foo { int x; }; void main() { foo x = foo(5); }",
    114                  "error: 1: cannot construct 'foo'\n1 error\n");
    115     test_failure(r,
    116                  "struct foo { int x; } foo; void main() { float x = float(foo); }",
    117                  "error: 1: invalid argument to 'float' constructor (expected a number or bool, but found 'foo')\n1 error\n");
    118     test_failure(r,
    119                  "struct foo { int x; } foo; void main() { float2 x = float2(foo); }",
    120                  "error: 1: 'foo' is not a valid parameter to 'float2' constructor\n1 error\n");
    121     test_failure(r,
    122                  "void main() { float2x2 x = float2x2(true); }",
    123                  "error: 1: expected 'float', but found 'bool'\n1 error\n");
    124 }
    125 
    126 DEF_TEST(SkSLConstructorArgumentCount, r) {
    127     test_failure(r,
    128                  "void main() { float3 x = float3(1.0, 2.0); }",
    129                  "error: 1: invalid arguments to 'float3' constructor (expected 3 scalars, but "
    130                  "found 2)\n1 error\n");
    131     test_failure(r,
    132                  "void main() { float3 x = float3(1.0, 2.0, 3.0, 4.0); }",
    133                  "error: 1: invalid arguments to 'float3' constructor (expected 3 scalars, but found "
    134                  "4)\n1 error\n");
    135 }
    136 
    137 DEF_TEST(SkSLSwizzleScalar, r) {
    138     test_failure(r,
    139                  "void main() { float x = 1; float y = x.y; }",
    140                  "error: 1: cannot swizzle value of type 'float'\n1 error\n");
    141 }
    142 
    143 DEF_TEST(SkSLSwizzleMatrix, r) {
    144     test_failure(r,
    145                  "void main() { float2x2 x = float2x2(1); float y = x.y; }",
    146                  "error: 1: cannot swizzle value of type 'float2x2'\n1 error\n");
    147 }
    148 
    149 DEF_TEST(SkSLSwizzleOutOfBounds, r) {
    150     test_failure(r,
    151                  "void main() { float3 test = float2(1).xyz; }",
    152                  "error: 1: invalid swizzle component 'z'\n1 error\n");
    153 }
    154 
    155 DEF_TEST(SkSLSwizzleTooManyComponents, r) {
    156     test_failure(r,
    157                  "void main() { float4 test = float2(1).xxxxx; }",
    158                  "error: 1: too many components in swizzle mask 'xxxxx'\n1 error\n");
    159 }
    160 
    161 DEF_TEST(SkSLSwizzleDuplicateOutput, r) {
    162     test_failure(r,
    163                  "void main() { float4 test = float4(1); test.xyyz = float4(1); }",
    164                  "error: 1: cannot write to the same swizzle field more than once\n1 error\n");
    165 }
    166 
    167 DEF_TEST(SkSLAssignmentTypeMismatch, r) {
    168     test_failure(r,
    169                  "void main() { int x = 1.0; }",
    170                  "error: 1: expected 'int', but found 'float'\n1 error\n");
    171     test_failure(r,
    172                  "void main() { int x; x = 1.0; }",
    173                  "error: 1: type mismatch: '=' cannot operate on 'int', 'float'\n1 error\n");
    174     test_success(r,
    175                  "void main() { float3 x = float3(0); x *= 1.0; }");
    176     test_failure(r,
    177                  "void main() { int3 x = int3(0); x *= 1.0; }",
    178                  "error: 1: type mismatch: '*=' cannot operate on 'int3', 'float'\n1 error\n");
    179 }
    180 
    181 DEF_TEST(SkSLReturnFromVoid, r) {
    182     test_failure(r,
    183                  "void main() { return true; }",
    184                  "error: 1: may not return a value from a void function\n1 error\n");
    185 }
    186 
    187 DEF_TEST(SkSLReturnMissingValue, r) {
    188     test_failure(r,
    189                  "int foo() { return; } void main() { }",
    190                  "error: 1: expected function to return 'int'\n1 error\n");
    191 }
    192 
    193 DEF_TEST(SkSLReturnTypeMismatch, r) {
    194     test_failure(r,
    195                  "int foo() { return 1.0; } void main() { }",
    196                  "error: 1: expected 'int', but found 'float'\n1 error\n");
    197 }
    198 
    199 DEF_TEST(SkSLDuplicateFunction, r) {
    200     test_failure(r,
    201                  "void main() { } void main() { }",
    202                  "error: 1: duplicate definition of void main()\n1 error\n");
    203     test_success(r,
    204                  "void main(); void main() { }");
    205 }
    206 
    207 DEF_TEST(SkSLUsingInvalidValue, r) {
    208     test_failure(r,
    209                  "void main() { int x = int; }",
    210                  "error: 1: expected '(' to begin constructor invocation\n1 error\n");
    211     test_failure(r,
    212                  "int test() { return 1; } void main() { int x = test; }",
    213                  "error: 1: expected '(' to begin function call\n1 error\n");
    214 }
    215 DEF_TEST(SkSLDifferentReturnType, r) {
    216     test_failure(r,
    217                  "int main() { return 1; } void main() { }",
    218                  "error: 1: functions 'void main()' and 'int main()' differ only in return type\n1 "
    219                  "error\n");
    220 }
    221 
    222 DEF_TEST(SkSLDifferentModifiers, r) {
    223     test_failure(r,
    224                  "void test(int x); void test(out int x) { }",
    225                  "error: 1: modifiers on parameter 1 differ between declaration and definition\n1 "
    226                  "error\n");
    227 }
    228 
    229 DEF_TEST(SkSLDuplicateSymbol, r) {
    230     test_failure(r,
    231                  "int main; void main() { }",
    232                  "error: 1: symbol 'main' was already defined\n1 error\n");
    233 
    234     test_failure(r,
    235                  "int x; int x; void main() { }",
    236                  "error: 1: symbol 'x' was already defined\n1 error\n");
    237 
    238     test_success(r, "int x; void main() { int x; }");
    239 }
    240 
    241 DEF_TEST(SkSLBinaryTypeMismatch, r) {
    242     test_failure(r,
    243                  "void main() { float x = 3 * true; }",
    244                  "error: 1: type mismatch: '*' cannot operate on 'int', 'bool'\n1 error\n");
    245     test_failure(r,
    246                  "void main() { bool x = 1 || 2.0; }",
    247                  "error: 1: type mismatch: '||' cannot operate on 'int', 'float'\n1 error\n");
    248 }
    249 
    250 DEF_TEST(SkSLCallNonFunction, r) {
    251     test_failure(r,
    252                  "void main() { float x = 3; x(); }",
    253                  "error: 1: 'x' is not a function\n1 error\n");
    254 }
    255 
    256 DEF_TEST(SkSLInvalidUnary, r) {
    257     test_failure(r,
    258                  "void main() { float4x4 x = float4x4(1); ++x; }",
    259                  "error: 1: '++' cannot operate on 'float4x4'\n1 error\n");
    260     test_failure(r,
    261                  "void main() { float3 x = float3(1); --x; }",
    262                  "error: 1: '--' cannot operate on 'float3'\n1 error\n");
    263     test_failure(r,
    264                  "void main() { float4x4 x = float4x4(1); x++; }",
    265                  "error: 1: '++' cannot operate on 'float4x4'\n1 error\n");
    266     test_failure(r,
    267                  "void main() { float3 x = float3(1); x--; }",
    268                  "error: 1: '--' cannot operate on 'float3'\n1 error\n");
    269     test_failure(r,
    270                  "void main() { int x = !12; }",
    271                  "error: 1: '!' cannot operate on 'int'\n1 error\n");
    272     test_failure(r,
    273                  "struct foo { } bar; void main() { foo x = +bar; }",
    274                  "error: 1: '+' cannot operate on 'foo'\n1 error\n");
    275     test_failure(r,
    276                  "struct foo { } bar; void main() { foo x = -bar; }",
    277                  "error: 1: '-' cannot operate on 'foo'\n1 error\n");
    278     test_success(r,
    279                  "void main() { float2 x = float2(1, 1); x = +x; x = -x; }");
    280 }
    281 
    282 DEF_TEST(SkSLInvalidAssignment, r) {
    283     test_failure(r,
    284                  "void main() { 1 = 2; }",
    285                  "error: 1: cannot assign to '1'\n1 error\n");
    286     test_failure(r,
    287                  "uniform int x; void main() { x = 0; }",
    288                  "error: 1: cannot modify immutable variable 'x'\n1 error\n");
    289     test_failure(r,
    290                  "const int x; void main() { x = 0; }",
    291                  "error: 1: cannot modify immutable variable 'x'\n1 error\n");
    292 }
    293 
    294 DEF_TEST(SkSLBadIndex, r) {
    295     test_failure(r,
    296                  "void main() { int x = 2[0]; }",
    297                  "error: 1: expected array, but found 'int'\n1 error\n");
    298     test_failure(r,
    299                  "void main() { float2 x = float2(0); int y = x[0][0]; }",
    300                  "error: 1: expected array, but found 'float'\n1 error\n");
    301 }
    302 
    303 DEF_TEST(SkSLTernaryMismatch, r) {
    304     test_failure(r,
    305                  "void main() { int x = 5 > 2 ? true : 1.0; }",
    306                  "error: 1: ternary operator result mismatch: 'bool', 'float'\n1 error\n");
    307     test_failure(r,
    308                  "void main() { int x = 5 > 2 ? float3(1) : 1.0; }",
    309                  "error: 1: ternary operator result mismatch: 'float3', 'float'\n1 error\n");
    310 }
    311 
    312 DEF_TEST(SkSLInterfaceBlockStorageModifiers, r) {
    313     test_failure(r,
    314                  "uniform foo { out int x; };",
    315                  "error: 1: interface block fields may not have storage qualifiers\n1 error\n");
    316 }
    317 
    318 DEF_TEST(SkSLUseWithoutInitialize, r) {
    319     test_failure(r,
    320                  "void main() { int x; if (5 == 2) x = 3; x++; }",
    321                  "error: 1: 'x' has not been assigned\n1 error\n");
    322     test_failure(r,
    323                  "void main() { int x[2][2]; int i; x[i][1] = 4; }",
    324                  "error: 1: 'i' has not been assigned\n1 error\n");
    325     test_failure(r,
    326                  "int main() { int r; return r; }",
    327                  "error: 1: 'r' has not been assigned\n1 error\n");
    328     test_failure(r,
    329                  "void main() { int x; int y = x; }",
    330                  "error: 1: 'x' has not been assigned\n1 error\n");
    331     test_failure(r,
    332                  "void main() { bool x; if (true && (false || x)) return; }",
    333                  "error: 1: 'x' has not been assigned\n1 error\n");
    334     test_failure(r,
    335                  "void main() { int x; switch (3) { case 0: x = 0; case 1: x = 1; }"
    336                                "sk_FragColor = float4(x); }",
    337                  "error: 1: 'x' has not been assigned\n1 error\n");
    338 }
    339 
    340 DEF_TEST(SkSLUnreachable, r) {
    341     test_failure(r,
    342                  "void main() { return; return; }",
    343                  "error: 1: unreachable\n1 error\n");
    344     test_failure(r,
    345                  "void main() { for (;;) { continue; int x = 1; } }",
    346                  "error: 1: unreachable\n1 error\n");
    347 /*    test_failure(r,
    348                  "void main() { for (;;) { } return; }",
    349                  "error: 1: unreachable\n1 error\n");*/
    350     test_failure(r,
    351                  "void main() { if (true) return; else discard; return; }",
    352                  "error: 1: unreachable\n1 error\n");
    353     test_failure(r,
    354                  "void main() { return; while (true); }",
    355                  "error: 1: unreachable\n1 error\n");
    356 }
    357 
    358 DEF_TEST(SkSLNoReturn, r) {
    359     test_failure(r,
    360                  "int foo() { if (2 > 5) return 3; }",
    361                  "error: 1: function can exit without returning a value\n1 error\n");
    362 }
    363 
    364 DEF_TEST(SkSLBreakOutsideLoop, r) {
    365     test_failure(r,
    366                  "void foo() { while(true) {} if (true) break; }",
    367                  "error: 1: break statement must be inside a loop or switch\n1 error\n");
    368 }
    369 
    370 DEF_TEST(SkSLContinueOutsideLoop, r) {
    371     test_failure(r,
    372                  "void foo() { for(;;); continue; }",
    373                  "error: 1: continue statement must be inside a loop\n1 error\n");
    374     test_failure(r,
    375                  "void foo() { switch (1) { default: continue; } }",
    376                  "error: 1: continue statement must be inside a loop\n1 error\n");
    377 }
    378 
    379 DEF_TEST(SkSLStaticIfError, r) {
    380     // ensure eliminated branch of static if / ternary is still checked for errors
    381     test_failure(r,
    382                  "void foo() { if (true); else x = 5; }",
    383                  "error: 1: unknown identifier 'x'\n1 error\n");
    384     test_failure(r,
    385                  "void foo() { if (false) x = 5; }",
    386                  "error: 1: unknown identifier 'x'\n1 error\n");
    387     test_failure(r,
    388                  "void foo() { true ? 5 : x; }",
    389                  "error: 1: unknown identifier 'x'\n1 error\n");
    390     test_failure(r,
    391                  "void foo() { false ? x : 5; }",
    392                  "error: 1: unknown identifier 'x'\n1 error\n");
    393 }
    394 
    395 DEF_TEST(SkSLBadCap, r) {
    396     test_failure(r,
    397                  "bool b = sk_Caps.bugFreeDriver;",
    398                  "error: 1: unknown capability flag 'bugFreeDriver'\n1 error\n");
    399 }
    400 
    401 DEF_TEST(SkSLDivByZero, r) {
    402     test_failure(r,
    403                  "int x = 1 / 0;",
    404                  "error: 1: division by zero\n1 error\n");
    405     test_failure(r,
    406                  "float x = 1 / 0;",
    407                  "error: 1: division by zero\n1 error\n");
    408     test_failure(r,
    409                  "float x = 1.0 / 0.0;",
    410                  "error: 1: division by zero\n1 error\n");
    411     test_failure(r,
    412                  "float x = -67.0 / (3.0 - 3);",
    413                  "error: 1: division by zero\n1 error\n");
    414 }
    415 
    416 DEF_TEST(SkSLUnsupportedGLSLIdentifiers, r) {
    417     test_failure(r,
    418                  "void main() { float x = gl_FragCoord.x; };",
    419                  "error: 1: unknown identifier 'gl_FragCoord'\n1 error\n");
    420     test_failure(r,
    421                  "void main() { float r = gl_FragColor.r; };",
    422                  "error: 1: unknown identifier 'gl_FragColor'\n1 error\n");
    423 }
    424 
    425 DEF_TEST(SkSLWrongSwitchTypes, r) {
    426     test_failure(r,
    427                  "void main() { switch (float2(1)) { case 1: break; } }",
    428                  "error: 1: expected 'int', but found 'float2'\n1 error\n");
    429     test_failure(r,
    430                  "void main() { switch (1) { case float2(1): break; } }",
    431                  "error: 1: expected 'int', but found 'float2'\n1 error\n");
    432 }
    433 
    434 DEF_TEST(SkSLNonConstantCase, r) {
    435     test_failure(r,
    436                  "void main() { int x = 1; switch (1) { case x: break; } }",
    437                  "error: 1: case value must be a constant\n1 error\n");
    438 }
    439 
    440 DEF_TEST(SkSLDuplicateCase, r) {
    441     test_failure(r,
    442                  "void main() { switch (1) { case 0: case 1: case 0: break; } }",
    443                  "error: 1: duplicate case value\n1 error\n");
    444 }
    445 
    446 DEF_TEST(SkSLFieldAfterRuntimeArray, r) {
    447     test_failure(r,
    448                  "buffer broken { float x[]; float y; };",
    449                  "error: 1: only the last entry in an interface block may be a runtime-sized "
    450                  "array\n1 error\n");
    451 }
    452 
    453 DEF_TEST(SkSLStaticIf, r) {
    454     test_success(r,
    455                  "void main() { float x = 5; float y = 10;"
    456                  "@if (x < y) { sk_FragColor = float4(1); } }");
    457     test_failure(r,
    458                  "void main() { float x = sqrt(25); float y = 10;"
    459                  "@if (x < y) { sk_FragColor = float4(1); } }",
    460                  "error: 1: static if has non-static test\n1 error\n");
    461 }
    462 
    463 DEF_TEST(SkSLStaticSwitch, r) {
    464     test_success(r,
    465                  "void main() {"
    466                  "int x = 1;"
    467                  "@switch (x) {"
    468                  "case 1: sk_FragColor = float4(1); break;"
    469                  "default: sk_FragColor = float4(0);"
    470                  "}"
    471                  "}");
    472     test_failure(r,
    473                  "void main() {"
    474                  "int x = int(sqrt(1));"
    475                  "@switch (x) {"
    476                  "case 1: sk_FragColor = float4(1); break;"
    477                  "default: sk_FragColor = float4(0);"
    478                  "}"
    479                  "}",
    480                  "error: 1: static switch has non-static test\n1 error\n");
    481     test_failure(r,
    482                  "void main() {"
    483                  "int x = 1;"
    484                  "@switch (x) {"
    485                  "case 1: sk_FragColor = float4(1); if (sqrt(0) < sqrt(1)) break;"
    486                  "default: sk_FragColor = float4(0);"
    487                  "}"
    488                  "}",
    489                  "error: 1: static switch contains non-static conditional break\n1 error\n");
    490 }
    491 
    492 DEF_TEST(SkSLInterfaceBlockScope, r) {
    493     test_failure(r,
    494                  "uniform testBlock {"
    495                  "float x;"
    496                  "} test[x];",
    497                  "error: 1: unknown identifier 'x'\n1 error\n");
    498 }
    499 
    500 #endif
    501