Browse Source

Updated spirv-tools.

Бранимир Караџић 6 years ago
parent
commit
631edf5e8d

+ 1 - 1
3rdparty/spirv-tools/include/generated/build-version.inc

@@ -1 +1 @@
-"v2019.5-dev", "SPIRV-Tools v2019.5-dev v2019.4-172-gc3f22f7c"
+"v2019.5-dev", "SPIRV-Tools v2019.5-dev v2019.4-178-g85f3e93d"

+ 9 - 0
3rdparty/spirv-tools/source/opt/ir_context.cpp

@@ -273,6 +273,14 @@ bool IRContext::IsConsistent() {
     }
     }
   }
   }
 
 
+  if (AreAnalysesValid(kAnalysisIdToFuncMapping)) {
+    for (auto& fn : *module_) {
+      if (id_to_func_[fn.result_id()] != &fn) {
+        return false;
+      }
+    }
+  }
+
   if (AreAnalysesValid(kAnalysisInstrToBlockMapping)) {
   if (AreAnalysesValid(kAnalysisInstrToBlockMapping)) {
     for (auto& func : *module()) {
     for (auto& func : *module()) {
       for (auto& block : func) {
       for (auto& block : func) {
@@ -818,6 +826,7 @@ bool IRContext::ProcessCallTreeFromRoots(ProcessFunction& pfn,
     roots->pop();
     roots->pop();
     if (done.insert(fi).second) {
     if (done.insert(fi).second) {
       Function* fn = GetFunction(fi);
       Function* fn = GetFunction(fi);
+      assert(fn && "Trying to process a function that does not exist.");
       modified = pfn(fn) || modified;
       modified = pfn(fn) || modified;
       AddCalls(fn, roots);
       AddCalls(fn, roots);
     }
     }

+ 1 - 1
3rdparty/spirv-tools/source/opt/value_number_table.cpp

@@ -93,7 +93,7 @@ uint32_t ValueNumberTable::AssignValueNumber(Instruction* inst) {
 
 
   // Phi nodes are a type of copy.  If all of the inputs have the same value
   // Phi nodes are a type of copy.  If all of the inputs have the same value
   // number, then we can assign the result of the phi the same value number.
   // number, then we can assign the result of the phi the same value number.
-  if (inst->opcode() == SpvOpPhi &&
+  if (inst->opcode() == SpvOpPhi && inst->NumInOperands() > 0 &&
       dec_mgr->HaveTheSameDecorations(inst->result_id(),
       dec_mgr->HaveTheSameDecorations(inst->result_id(),
                                       inst->GetSingleWordInOperand(0))) {
                                       inst->GetSingleWordInOperand(0))) {
     value = GetValueNumber(inst->GetSingleWordInOperand(0));
     value = GetValueNumber(inst->GetSingleWordInOperand(0));

+ 1 - 2
3rdparty/spirv-tools/source/opt/wrap_opkill.h

@@ -34,8 +34,7 @@ class WrapOpKill : public Pass {
            IRContext::kAnalysisInstrToBlockMapping |
            IRContext::kAnalysisInstrToBlockMapping |
            IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators |
            IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators |
            IRContext::kAnalysisNameMap | IRContext::kAnalysisBuiltinVarId |
            IRContext::kAnalysisNameMap | IRContext::kAnalysisBuiltinVarId |
-           IRContext::kAnalysisIdToFuncMapping | IRContext::kAnalysisConstants |
-           IRContext::kAnalysisTypes;
+           IRContext::kAnalysisConstants | IRContext::kAnalysisTypes;
   }
   }
 
 
  private:
  private:

+ 3 - 1
3rdparty/spirv-tools/test/fuzzers/spvtools_as_fuzzer.cpp

@@ -36,7 +36,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   input_str.resize(char_count);
   input_str.resize(char_count);
   memcpy(input_str.data(), input.data(), input.size() * sizeof(uint32_t));
   memcpy(input_str.data(), input.data(), input.size() * sizeof(uint32_t));
 
 
-  spv_binary binary;
+  spv_binary binary = nullptr;
   spv_diagnostic diagnostic = nullptr;
   spv_diagnostic diagnostic = nullptr;
   spvTextToBinaryWithOptions(context, input_str.data(), input_str.size(),
   spvTextToBinaryWithOptions(context, input_str.data(), input_str.size(),
                              SPV_TEXT_TO_BINARY_OPTION_NONE, &binary,
                              SPV_TEXT_TO_BINARY_OPTION_NONE, &binary,
@@ -66,5 +66,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
     binary = nullptr;
     binary = nullptr;
   }
   }
 
 
+  spvContextDestroy(context);
+
   return 0;
   return 0;
 }
 }

+ 31 - 0
3rdparty/spirv-tools/test/opt/value_table_test.cpp

@@ -653,6 +653,37 @@ TEST_F(ValueTableTest, PhiLoopTest) {
   EXPECT_NE(vtable.GetValueNumber(phi1), vtable.GetValueNumber(phi2));
   EXPECT_NE(vtable.GetValueNumber(phi1), vtable.GetValueNumber(phi2));
 }
 }
 
 
+// Test to make sure that OpPhi instructions with no in operands are handled
+// correctly.
+TEST_F(ValueTableTest, EmptyPhiTest) {
+  const std::string text = R"(
+               OpCapability Shader
+          %1 = OpExtInstImport "GLSL.std.450"
+               OpMemoryModel Logical GLSL450
+               OpEntryPoint Fragment %2 "main"
+               OpExecutionMode %2 OriginUpperLeft
+               OpSource GLSL 430
+       %void = OpTypeVoid
+          %4 = OpTypeFunction %void
+       %bool = OpTypeBool
+       %true = OpConstantTrue %bool
+          %2 = OpFunction %void None %4
+          %7 = OpLabel
+               OpSelectionMerge %8 None
+               OpBranchConditional %true %9 %8
+          %9 = OpLabel
+               OpKill
+          %8 = OpLabel
+         %10 = OpPhi %bool
+               OpReturn
+               OpFunctionEnd
+  )";
+  auto context = BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
+  ValueNumberTable vtable(context.get());
+  Instruction* inst = context->get_def_use_mgr()->GetDef(10);
+  vtable.GetValueNumber(inst);
+}
+
 }  // namespace
 }  // namespace
 }  // namespace opt
 }  // namespace opt
 }  // namespace spvtools
 }  // namespace spvtools

+ 6 - 3
3rdparty/spirv-tools/test/tools/CMakeLists.txt

@@ -12,7 +12,10 @@
 # See the License for the specific language governing permissions and
 # See the License for the specific language governing permissions and
 # limitations under the License.
 # limitations under the License.
 
 
-spirv_add_nosetests(expect)
-spirv_add_nosetests(spirv_test_framework)
-
+add_test(NAME spirv-tools_expect_unittests
+         COMMAND ${PYTHON_EXECUTABLE} -m unittest expect_unittest.py
+         WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+add_test(NAME spirv-tools_spirv_test_framework_unittests
+         COMMAND ${PYTHON_EXECUTABLE} -m unittest spirv_test_framework_unittest.py
+         WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
 add_subdirectory(opt)
 add_subdirectory(opt)

+ 8 - 8
3rdparty/spirv-tools/test/tools/expect.py

@@ -510,7 +510,7 @@ class ErrorMessageSubstr(SpirvTest):
     if not status.stderr:
     if not status.stderr:
       return False, 'Expected error message, but no output on stderr'
       return False, 'Expected error message, but no output on stderr'
     if self.expected_error_substr not in convert_to_unix_line_endings(
     if self.expected_error_substr not in convert_to_unix_line_endings(
-        status.stderr.decode('utf8')):
+        status.stderr):
       return False, ('Incorrect stderr output:\n{act}\n'
       return False, ('Incorrect stderr output:\n{act}\n'
                      'Expected substring not found in stderr:\n{exp}'.format(
                      'Expected substring not found in stderr:\n{exp}'.format(
                          act=status.stderr, exp=self.expected_error_substr))
                          act=status.stderr, exp=self.expected_error_substr))
@@ -530,7 +530,7 @@ class WarningMessage(SpirvTest):
                      ' command execution')
                      ' command execution')
     if not status.stderr:
     if not status.stderr:
       return False, 'Expected warning message, but no output on stderr'
       return False, 'Expected warning message, but no output on stderr'
-    if self.expected_warning != convert_to_unix_line_endings(status.stderr.decode('utf8')):
+    if self.expected_warning != convert_to_unix_line_endings(status.stderr):
       return False, ('Incorrect stderr output:\n{act}\n'
       return False, ('Incorrect stderr output:\n{act}\n'
                      'Expected:\n{exp}'.format(
                      'Expected:\n{exp}'.format(
                          act=status.stderr, exp=self.expected_warning))
                          act=status.stderr, exp=self.expected_warning))
@@ -590,16 +590,16 @@ class StdoutMatch(SpirvTest):
       if not status.stdout:
       if not status.stdout:
         return False, 'Expected something on stdout'
         return False, 'Expected something on stdout'
     elif type(self.expected_stdout) == str:
     elif type(self.expected_stdout) == str:
-      if self.expected_stdout != convert_to_unix_line_endings(status.stdout.decode('utf8')):
+      if self.expected_stdout != convert_to_unix_line_endings(status.stdout):
         return False, ('Incorrect stdout output:\n{ac}\n'
         return False, ('Incorrect stdout output:\n{ac}\n'
                        'Expected:\n{ex}'.format(
                        'Expected:\n{ex}'.format(
                            ac=status.stdout, ex=self.expected_stdout))
                            ac=status.stdout, ex=self.expected_stdout))
     else:
     else:
-      converted = convert_to_unix_line_endings(status.stdout.decode('utf8'))
+      converted = convert_to_unix_line_endings(status.stdout)
       if not self.expected_stdout.search(converted):
       if not self.expected_stdout.search(converted):
         return False, ('Incorrect stdout output:\n{ac}\n'
         return False, ('Incorrect stdout output:\n{ac}\n'
                        'Expected to match regex:\n{ex}'.format(
                        'Expected to match regex:\n{ex}'.format(
-                           ac=status.stdout.decode('utf8'), ex=self.expected_stdout.pattern))
+                           ac=status.stdout, ex=self.expected_stdout.pattern))
     return True, ''
     return True, ''
 
 
 
 
@@ -624,13 +624,13 @@ class StderrMatch(SpirvTest):
       if not status.stderr:
       if not status.stderr:
         return False, 'Expected something on stderr'
         return False, 'Expected something on stderr'
     elif type(self.expected_stderr) == str:
     elif type(self.expected_stderr) == str:
-      if self.expected_stderr != convert_to_unix_line_endings(status.stderr.decode('utf8')):
+      if self.expected_stderr != convert_to_unix_line_endings(status.stderr):
         return False, ('Incorrect stderr output:\n{ac}\n'
         return False, ('Incorrect stderr output:\n{ac}\n'
                        'Expected:\n{ex}'.format(
                        'Expected:\n{ex}'.format(
                            ac=status.stderr, ex=self.expected_stderr))
                            ac=status.stderr, ex=self.expected_stderr))
     else:
     else:
       if not self.expected_stderr.search(
       if not self.expected_stderr.search(
-          convert_to_unix_line_endings(status.stderr.decode('utf8'))):
+          convert_to_unix_line_endings(status.stderr)):
         return False, ('Incorrect stderr output:\n{ac}\n'
         return False, ('Incorrect stderr output:\n{ac}\n'
                        'Expected to match regex:\n{ex}'.format(
                        'Expected to match regex:\n{ex}'.format(
                            ac=status.stderr, ex=self.expected_stderr.pattern))
                            ac=status.stderr, ex=self.expected_stderr.pattern))
@@ -695,7 +695,7 @@ class ExecutedListOfPasses(SpirvTest):
     # Collect all the output lines containing a pass name.
     # Collect all the output lines containing a pass name.
     pass_names = []
     pass_names = []
     pass_name_re = re.compile(r'.*IR before pass (?P<pass_name>[\S]+)')
     pass_name_re = re.compile(r'.*IR before pass (?P<pass_name>[\S]+)')
-    for line in status.stderr.decode('utf8').splitlines():
+    for line in status.stderr.splitlines():
       match = pass_name_re.match(line)
       match = pass_name_re.match(line)
       if match:
       if match:
         pass_names.append(match.group('pass_name'))
         pass_names.append(match.group('pass_name'))

+ 0 - 80
3rdparty/spirv-tools/test/tools/expect_nosetest.py

@@ -1,80 +0,0 @@
-# Copyright (c) 2018 Google LLC
-#
-# 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.
-"""Tests for the expect module."""
-
-import expect
-from spirv_test_framework import TestStatus
-from nose.tools import assert_equal, assert_true, assert_false
-import re
-
-
-def nosetest_get_object_name():
-  """Tests get_object_filename()."""
-  source_and_object_names = [('a.vert', 'a.vert.spv'), ('b.frag', 'b.frag.spv'),
-                             ('c.tesc', 'c.tesc.spv'), ('d.tese', 'd.tese.spv'),
-                             ('e.geom', 'e.geom.spv'), ('f.comp', 'f.comp.spv'),
-                             ('file', 'file.spv'), ('file.', 'file.spv'),
-                             ('file.uk',
-                              'file.spv'), ('file.vert.',
-                                            'file.vert.spv'), ('file.vert.bla',
-                                                               'file.vert.spv')]
-  actual_object_names = [
-      expect.get_object_filename(f[0]) for f in source_and_object_names
-  ]
-  expected_object_names = [f[1] for f in source_and_object_names]
-
-  assert_equal(actual_object_names, expected_object_names)
-
-
-class TestStdoutMatchADotC(expect.StdoutMatch):
-  expected_stdout = re.compile('a.c')
-
-
-def nosetest_stdout_match_regex_has_match():
-  test = TestStdoutMatchADotC()
-  status = TestStatus(
-      test_manager=None,
-      returncode=0,
-      stdout='0abc1',
-      stderr=None,
-      directory=None,
-      inputs=None,
-      input_filenames=None)
-  assert_true(test.check_stdout_match(status)[0])
-
-
-def nosetest_stdout_match_regex_no_match():
-  test = TestStdoutMatchADotC()
-  status = TestStatus(
-      test_manager=None,
-      returncode=0,
-      stdout='ab',
-      stderr=None,
-      directory=None,
-      inputs=None,
-      input_filenames=None)
-  assert_false(test.check_stdout_match(status)[0])
-
-
-def nosetest_stdout_match_regex_empty_stdout():
-  test = TestStdoutMatchADotC()
-  status = TestStatus(
-      test_manager=None,
-      returncode=0,
-      stdout='',
-      stderr=None,
-      directory=None,
-      inputs=None,
-      input_filenames=None)
-  assert_false(test.check_stdout_match(status)[0])

+ 82 - 0
3rdparty/spirv-tools/test/tools/expect_unittest.py

@@ -0,0 +1,82 @@
+# Copyright (c) 2019 Google LLC
+#
+# 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.
+"""Tests for the expect module."""
+
+import expect
+from spirv_test_framework import TestStatus
+import re
+import unittest
+
+
+class TestStdoutMatchADotC(expect.StdoutMatch):
+    expected_stdout = re.compile('a.c')
+
+
+class TestExpect(unittest.TestCase):
+    def test_get_object_name(self):
+        """Tests get_object_filename()."""
+        source_and_object_names = [('a.vert', 'a.vert.spv'),
+                                   ('b.frag', 'b.frag.spv'),
+                                   ('c.tesc', 'c.tesc.spv'),
+                                   ('d.tese', 'd.tese.spv'),
+                                   ('e.geom', 'e.geom.spv'),
+                                   ('f.comp', 'f.comp.spv'),
+                                   ('file', 'file.spv'), ('file.', 'file.spv'),
+                                   ('file.uk',
+                                    'file.spv'), ('file.vert.',
+                                                  'file.vert.spv'),
+                                   ('file.vert.bla',
+                                    'file.vert.spv')]
+        actual_object_names = [
+            expect.get_object_filename(f[0]) for f in source_and_object_names
+        ]
+        expected_object_names = [f[1] for f in source_and_object_names]
+
+        self.assertEqual(actual_object_names, expected_object_names)
+
+    def test_stdout_match_regex_has_match(self):
+        test = TestStdoutMatchADotC()
+        status = TestStatus(
+            test_manager=None,
+            returncode=0,
+            stdout=b'0abc1',
+            stderr=None,
+            directory=None,
+            inputs=None,
+            input_filenames=None)
+        self.assertTrue(test.check_stdout_match(status)[0])
+
+    def test_stdout_match_regex_no_match(self):
+        test = TestStdoutMatchADotC()
+        status = TestStatus(
+            test_manager=None,
+            returncode=0,
+            stdout=b'ab',
+            stderr=None,
+            directory=None,
+            inputs=None,
+            input_filenames=None)
+        self.assertFalse(test.check_stdout_match(status)[0])
+
+    def test_stdout_match_regex_empty_stdout(self):
+        test = TestStdoutMatchADotC()
+        status = TestStatus(
+            test_manager=None,
+            returncode=0,
+            stdout=b'',
+            stderr=None,
+            directory=None,
+            inputs=None,
+            input_filenames=None)
+        self.assertFalse(test.check_stdout_match(status)[0])

+ 26 - 5
3rdparty/spirv-tools/test/tools/spirv_test_framework.py

@@ -70,7 +70,7 @@ def get_all_methods(instance):
 
 
 
 
 def get_all_superclasses(cls):
 def get_all_superclasses(cls):
-  """Returns all superclasses of a given class.
+  """Returns all superclasses of a given class. Omits root 'object' superclass.
 
 
     Returns:
     Returns:
       A list of superclasses of the given class. The order guarantees that
       A list of superclasses of the given class. The order guarantees that
@@ -83,11 +83,12 @@ def get_all_superclasses(cls):
   classes = []
   classes = []
   for superclass in cls.__bases__:
   for superclass in cls.__bases__:
     for c in get_all_superclasses(superclass):
     for c in get_all_superclasses(superclass):
-      if c not in classes:
+      if c is not object and c not in classes:
         classes.append(c)
         classes.append(c)
   for superclass in cls.__bases__:
   for superclass in cls.__bases__:
-    if superclass not in classes:
+    if superclass is not object and superclass not in classes:
       classes.append(superclass)
       classes.append(superclass)
+
   return classes
   return classes
 
 
 
 
@@ -142,8 +143,28 @@ class TestStatus:
                inputs, input_filenames):
                inputs, input_filenames):
     self.test_manager = test_manager
     self.test_manager = test_manager
     self.returncode = returncode
     self.returncode = returncode
-    self.stdout = stdout
-    self.stderr = stderr
+    # Some of our MacOS bots still run Python 2, so need to be backwards
+    # compatible here.
+    if type(stdout) is not str:     
+      if sys.version_info[0] is 2:
+       self.stdout = stdout.decode('utf-8')
+      elif sys.version_info[0] is 3:
+        self.stdout = str(stdout, encoding='utf-8') if stdout is not None else stdout
+      else:
+        raise Exception('Unable to determine if running Python 2 or 3 from {}'.format(sys.version_info))
+    else:
+      self.stdout = stdout
+    
+    if type(stderr) is not str:     
+      if sys.version_info[0] is 2:
+       self.stderr = stderr.decode('utf-8')
+      elif sys.version_info[0] is 3:
+        self.stderr = str(stderr, encoding='utf-8') if stderr is not None else stderr
+      else:
+        raise Exception('Unable to determine if running Python 2 or 3 from {}'.format(sys.version_info))
+    else:
+      self.stderr = stderr
+
     # temporary directory where the test runs
     # temporary directory where the test runs
     self.directory = directory
     self.directory = directory
     # List of inputs, as PlaceHolder objects.
     # List of inputs, as PlaceHolder objects.

+ 0 - 155
3rdparty/spirv-tools/test/tools/spirv_test_framework_nosetest.py

@@ -1,155 +0,0 @@
-# Copyright (c) 2018 Google LLC
-#
-# 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.
-
-from spirv_test_framework import get_all_test_methods, get_all_superclasses
-from nose.tools import assert_equal, with_setup
-
-
-# Classes to be used in testing get_all_{superclasses|test_methods}()
-class Root:
-
-  def check_root(self):
-    pass
-
-
-class A(Root):
-
-  def check_a(self):
-    pass
-
-
-class B(Root):
-
-  def check_b(self):
-    pass
-
-
-class C(Root):
-
-  def check_c(self):
-    pass
-
-
-class D(Root):
-
-  def check_d(self):
-    pass
-
-
-class E(Root):
-
-  def check_e(self):
-    pass
-
-
-class H(B, C, D):
-
-  def check_h(self):
-    pass
-
-
-class I(E):
-
-  def check_i(self):
-    pass
-
-
-class O(H, I):
-
-  def check_o(self):
-    pass
-
-
-class U(A, O):
-
-  def check_u(self):
-    pass
-
-
-class X(U, A):
-
-  def check_x(self):
-    pass
-
-
-class R1:
-
-  def check_r1(self):
-    pass
-
-
-class R2:
-
-  def check_r2(self):
-    pass
-
-
-class Multi(R1, R2):
-
-  def check_multi(self):
-    pass
-
-
-def nosetest_get_all_superclasses():
-  """Tests get_all_superclasses()."""
-
-  assert_equal(get_all_superclasses(A), [Root])
-  assert_equal(get_all_superclasses(B), [Root])
-  assert_equal(get_all_superclasses(C), [Root])
-  assert_equal(get_all_superclasses(D), [Root])
-  assert_equal(get_all_superclasses(E), [Root])
-
-  assert_equal(get_all_superclasses(H), [Root, B, C, D])
-  assert_equal(get_all_superclasses(I), [Root, E])
-
-  assert_equal(get_all_superclasses(O), [Root, B, C, D, E, H, I])
-
-  assert_equal(get_all_superclasses(U), [Root, B, C, D, E, H, I, A, O])
-  assert_equal(get_all_superclasses(X), [Root, B, C, D, E, H, I, A, O, U])
-
-  assert_equal(get_all_superclasses(Multi), [R1, R2])
-
-
-def nosetest_get_all_methods():
-  """Tests get_all_test_methods()."""
-  assert_equal(get_all_test_methods(A), ['check_root', 'check_a'])
-  assert_equal(get_all_test_methods(B), ['check_root', 'check_b'])
-  assert_equal(get_all_test_methods(C), ['check_root', 'check_c'])
-  assert_equal(get_all_test_methods(D), ['check_root', 'check_d'])
-  assert_equal(get_all_test_methods(E), ['check_root', 'check_e'])
-
-  assert_equal(
-      get_all_test_methods(H),
-      ['check_root', 'check_b', 'check_c', 'check_d', 'check_h'])
-  assert_equal(get_all_test_methods(I), ['check_root', 'check_e', 'check_i'])
-
-  assert_equal(
-      get_all_test_methods(O), [
-          'check_root', 'check_b', 'check_c', 'check_d', 'check_e', 'check_h',
-          'check_i', 'check_o'
-      ])
-
-  assert_equal(
-      get_all_test_methods(U), [
-          'check_root', 'check_b', 'check_c', 'check_d', 'check_e', 'check_h',
-          'check_i', 'check_a', 'check_o', 'check_u'
-      ])
-  assert_equal(
-      get_all_test_methods(X), [
-          'check_root', 'check_b', 'check_c', 'check_d', 'check_e', 'check_h',
-          'check_i', 'check_a', 'check_o', 'check_u', 'check_x'
-      ])
-
-  assert_equal(
-      get_all_test_methods(Multi), ['check_r1', 'check_r2', 'check_multi'])

+ 158 - 0
3rdparty/spirv-tools/test/tools/spirv_test_framework_unittest.py

@@ -0,0 +1,158 @@
+# Copyright (c) 2019 Google LLC
+#
+# 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.
+"""Tests for the spirv test framework module."""
+
+from spirv_test_framework import get_all_test_methods, get_all_superclasses
+import unittest
+
+# Classes to be used in testing get_all_{superclasses|test_methods}()
+
+
+class Root:
+
+    def check_root(self):
+        pass
+
+
+class A(Root):
+
+    def check_a(self):
+        pass
+
+
+class B(Root):
+
+    def check_b(self):
+        pass
+
+
+class C(Root):
+
+    def check_c(self):
+        pass
+
+
+class D(Root):
+
+    def check_d(self):
+        pass
+
+
+class E(Root):
+
+    def check_e(self):
+        pass
+
+
+class H(B, C, D):
+
+    def check_h(self):
+        pass
+
+
+class I(E):
+
+    def check_i(self):
+        pass
+
+
+class O(H, I):
+
+    def check_o(self):
+        pass
+
+
+class U(A, O):
+
+    def check_u(self):
+        pass
+
+
+class X(U, A):
+
+    def check_x(self):
+        pass
+
+
+class R1:
+
+    def check_r1(self):
+        pass
+
+
+class R2:
+
+    def check_r2(self):
+        pass
+
+
+class Multi(R1, R2):
+
+    def check_multi(self):
+        pass
+
+
+class TestSpirvTestFramework(unittest.TestCase):
+    def test_get_all_superclasses(self):
+        self.assertEqual(get_all_superclasses(A), [Root])
+        self.assertEqual(get_all_superclasses(B), [Root])
+        self.assertEqual(get_all_superclasses(C), [Root])
+        self.assertEqual(get_all_superclasses(D), [Root])
+        self.assertEqual(get_all_superclasses(E), [Root])
+
+        self.assertEqual(get_all_superclasses(H), [Root, B, C, D])
+        self.assertEqual(get_all_superclasses(I), [Root, E])
+
+        self.assertEqual(get_all_superclasses(O), [Root, B, C, D, E, H, I])
+
+        self.assertEqual(get_all_superclasses(
+            U), [Root, B, C, D, E, H, I, A, O])
+        self.assertEqual(get_all_superclasses(
+            X), [Root, B, C, D, E, H, I, A, O, U])
+
+        self.assertEqual(get_all_superclasses(Multi), [R1, R2])
+
+    def test_get_all_methods(self):
+        self.assertEqual(get_all_test_methods(A), ['check_root', 'check_a'])
+        self.assertEqual(get_all_test_methods(B), ['check_root', 'check_b'])
+        self.assertEqual(get_all_test_methods(C), ['check_root', 'check_c'])
+        self.assertEqual(get_all_test_methods(D), ['check_root', 'check_d'])
+        self.assertEqual(get_all_test_methods(E), ['check_root', 'check_e'])
+
+        self.assertEqual(
+            get_all_test_methods(H),
+            ['check_root', 'check_b', 'check_c', 'check_d', 'check_h'])
+        self.assertEqual(get_all_test_methods(
+            I), ['check_root', 'check_e', 'check_i'])
+
+        self.assertEqual(
+            get_all_test_methods(O), [
+                'check_root', 'check_b', 'check_c', 'check_d', 'check_e', 'check_h',
+                'check_i', 'check_o'
+            ])
+
+        self.assertEqual(
+            get_all_test_methods(U), [
+                'check_root', 'check_b', 'check_c', 'check_d', 'check_e', 'check_h',
+                'check_i', 'check_a', 'check_o', 'check_u'
+            ])
+
+        self.assertEqual(
+            get_all_test_methods(X), [
+                'check_root', 'check_b', 'check_c', 'check_d', 'check_e', 'check_h',
+                'check_i', 'check_a', 'check_o', 'check_u', 'check_x'
+            ])
+
+        self.assertEqual(
+            get_all_test_methods(Multi), ['check_r1', 'check_r2', 'check_multi'])