blob: aeda86e09d064a0cc4e061a6d7fa6dcb9e5f25f2 [file] [log] [blame]
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validate
import (
"testing"
"android.googlesource.com/platform/tools/gpu/api/apic/commands"
"android.googlesource.com/platform/tools/gpu/api/ast"
"android.googlesource.com/platform/tools/gpu/api/parser"
"android.googlesource.com/platform/tools/gpu/api/resolver"
"android.googlesource.com/platform/tools/gpu/api/semantic"
)
func compile(t *testing.T, source string) (*semantic.API, error) {
parsed, errs := parser.Parse(source)
if err := commands.CheckErrors(source, errs); err != nil {
return nil, err
}
compiled, errs := resolver.Resolve([]*ast.API{parsed}, nil, resolver.ASTToSemantic{})
if err := commands.CheckErrors(source, errs); err != nil {
return nil, err
}
return compiled, nil
}
type expectedError struct {
line int
column int
msg string
}
type test struct {
source string
expected []expectedError
}
func TestSimpleUnreachable(t *testing.T) {
expect := func(errs ...expectedError) []expectedError {
return errs
}
unreachable := func(l, c int) expectedError {
return expectedError{l, c, "Unreachable block"}
}
for _, test := range []test{
// Bool tests
{`s32 x = 0
cmd void f() {
if (true) { x = 1 }
}`, expect()},
{`s32 x = 0
cmd void f() {
if (true) { x = 1 } else {}
}`, expect()},
{`s32 x = 0
cmd void f() {
if (false) {} else { x = 2 }
}`, expect()},
{`s32 x = 0
cmd void f() {
a := false
if (a) { x = 1 } else { x = 2 }
}`, expect(unreachable(4, 16))},
{`s32 x = 0
cmd void f() {
a := true
if (a) { x = 1 } else { x = 2 }
}`, expect(unreachable(4, 31))},
{`s32 x = 0
cmd void f() {
a := true == false
if (a) { x = 1 } else { x = 2 }
}`, expect(unreachable(4, 16))},
{`s32 x = 0
cmd void f() {
a := true && false
if (a) { x = 1 } else { x = 2 }
}`, expect(unreachable(4, 16))},
{`s32 x = 0
cmd void f() {
a := true || false
if (a) { x = 1 } else { x = 2 }
}`, expect(unreachable(4, 31))},
{`s32 x = 0
cmd void f(bool a) {
if (a) { if (!a) { x = 1 } }
if (!a) { if (a) { x = 1 } }
if (a) {} else if (a) { x = 1 }
if (!a) {} else if (!a) { x = 1 }
}`, expect(
unreachable(3, 26),
unreachable(4, 26),
unreachable(5, 31),
unreachable(6, 33),
)},
{`s32 x = 0
cmd void f(bool v) {
assert(v)
if (v) { x = 1 } else { x = 2 }
}`, expect(unreachable(4, 31))},
// Uint tests
{`s32 x = 0
cmd void f(u32 a) {
if (a > 5) { x = 1 } else { x = 2 }
}`, expect()},
{`s32 x = 0
cmd void f() {
a := as!u32(5)
if (a > 4) { x = 1 } else { x = 2 }
if (a > 5) { x = 1 } else { x = 2 }
if (a > 6) { x = 1 } else { x = 2 }
if (4 > a) { x = 1 } else { x = 2 }
if (5 > a) { x = 1 } else { x = 2 }
if (6 > a) { x = 1 } else { x = 2 }
}`, expect(
unreachable(4, 35),
unreachable(5, 20),
unreachable(6, 20),
unreachable(7, 20),
unreachable(8, 20),
unreachable(9, 35),
)},
{`s32 x = 0
cmd void f() {
a := as!u32(5)
if (a >= 4) { x = 1 } else { x = 2 }
if (a >= 5) { x = 1 } else { x = 2 }
if (a >= 6) { x = 1 } else { x = 2 }
if (4 >= a) { x = 1 } else { x = 2 }
if (5 >= a) { x = 1 } else { x = 2 }
if (6 >= a) { x = 1 } else { x = 2 }
}`, expect(
unreachable(4, 36),
unreachable(5, 36),
unreachable(6, 21),
unreachable(7, 21),
unreachable(8, 36),
unreachable(9, 36),
)},
{`s32 x = 0
cmd void f() {
a := as!u32(5)
if (a < 4) { x = 1 } else { x = 2 }
if (a < 5) { x = 1 } else { x = 2 }
if (a < 6) { x = 1 } else { x = 2 }
if (4 < a) { x = 1 } else { x = 2 }
if (5 < a) { x = 1 } else { x = 2 }
if (6 < a) { x = 1 } else { x = 2 }
}`, expect(
unreachable(4, 20),
unreachable(5, 20),
unreachable(6, 35),
unreachable(7, 35),
unreachable(8, 20),
unreachable(9, 20),
)},
{`s32 x = 0
cmd void f() {
a := as!u32(5)
if (a <= 4) { x = 1 } else { x = 2 }
if (a <= 5) { x = 1 } else { x = 2 }
if (a <= 6) { x = 1 } else { x = 2 }
if (4 <= a) { x = 1 } else { x = 2 }
if (5 <= a) { x = 1 } else { x = 2 }
if (6 <= a) { x = 1 } else { x = 2 }
}`, expect(
unreachable(4, 21),
unreachable(5, 36),
unreachable(6, 36),
unreachable(7, 36),
unreachable(8, 36),
unreachable(9, 21),
)},
{`s32 x = 0
cmd void f() {
a := as!u32(5)
if (a == 4) { x = 1 } else { x = 2 }
if (a == 5) { x = 1 } else { x = 2 }
if (a == 6) { x = 1 } else { x = 2 }
}`, expect(
unreachable(4, 21),
unreachable(5, 36),
unreachable(6, 21),
)},
} {
api, err := compile(t, test.source)
if err != nil {
t.Errorf("API compile failed with %s", err)
return
}
if api == nil {
t.Errorf("API compiled but was nil")
return
}
got := noUnreachables(api)
ok := true
if len(got) == len(test.expected) {
for i := range got {
l, c := got[i].At.Token().Cursor()
if l != test.expected[i].line ||
c != test.expected[i].column ||
got[i].Message != test.expected[i].msg {
ok = false
}
}
} else {
ok = false
}
if !ok {
t.Errorf("Errors were not as expected for:\n%s\n\n Got: %+v, Wanted: %+v", test.source, got, test.expected)
}
}
}