Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Google Test as the new test framework #190

Merged
merged 1 commit into from
Mar 31, 2016

Conversation

antiagainst
Copy link
Contributor

Addresses #189.

This patch add Google Test as an external project for future unit tests and subsuming the responsibility of runtests.

@antiagainst
Copy link
Contributor Author

@johnkslang I've just converted two existing tests as a demo. PTAL and share your opinions on this approach.

It turns out with googletest TotT, we can have diff if output is different from expected, which is quite nice!

[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from GlslangTest
[ RUN      ] GlslangTest.VertexShader140
../gtests/Spv.General.cpp:75: Failure
      Expected: expected_disassembly
      Which is: "\nspv.test.vert\nWARNING: 0:5: attribute deprecated in version 130; may be removed in future release\n\n\nLinked vertex stage:\n\n\n// Module Version 10000\n// Generate
d by (magic number): 80001\n// Id's are bound by 24\n\n                              Capability Shader\n               1:             ExtInstImport  \"GLSL.std.450\"\n                  
            MemoryModel Logical GLSL450\n                              EntryPoint Vertex 4  \"main\" 9 11 15 18 21\n                              Source GLSL 140\n                      
        Name 4  \"main\"\n                              Name 9  \"uv\"\n                              Name 11  \"uv_in\"\n                              Name 15  \"gl_Position\"\n       
                       Name 18  \"transform\"\n                              Name 21  \"position\"\n                              Decorate 15(gl_Position) BuiltIn Position\n            
   2:             TypeVoid\n               3:             TypeFunction 2\n               6:             TypeFloat 32\n               7:             TypeVector 6(float) 2\n              
 8:             TypePointer Output 7(fvec2)\n           9(uv):      8(ptr) Variable Output\n              10:             TypePointer Input 7(fvec2)\n       11(uv_in):     10(ptr) Varia
ble Input\n              13:             TypeVector 6(float) 4\n              14:             TypePointer Output 13(fvec4)\n 15(gl_Position):     14(ptr) Variable Output\n              
16:             TypeMatrix 13(fvec4) 4\n              17:             TypePointer Input 16\n   18(transform):     17(ptr) Variable Input\n              20:             TypePointer Input
 13(fvec4)\n    21(position):     20(ptr) Variable Input\n         4(main):           2 Function None 3\n               5:             Label\n              12:    7(fvec2) Load 11(uv_in
)\n                              Store 9(uv) 12\n              19:          16 Load 18(transform)\n              22:   13(fvec4) Load 21(position)\n              23:   13(fvec4) MatrixT
imesVector 19 22\n                              Store 15(gl_Position) 23\n                              Return\n                              FunctionEnd\n"
To be equal to: CompileGlslToSpirv(source, EShLangVertex)
      Which is: "// Module Version 10000\n// Generated by (magic number): 80001\n// Id's are bound by 28\n\n                              Capability Shader\n               1:           
  ExtInstImport  \"GLSL.std.450\"\n                              MemoryModel Logical GLSL450\n                              EntryPoint Vertex 4  \"main\" 9 11 15 18 21 26 27\n          
                    Source GLSL 140\n                              Name 4  \"main\"\n                              Name 9  \"uv\"\n                              Name 11  \"uv_in\"\n    
                          Name 15  \"gl_Position\"\n                              Name 18  \"transform\"\n                              Name 21  \"position\"\n                          
    Name 26  \"gl_VertexID\"\n                              Name 27  \"gl_InstanceID\"\n                              Decorate 15(gl_Position) BuiltIn Position\n                        
      Decorate 26(gl_VertexID) BuiltIn VertexId\n                              Decorate 27(gl_InstanceID) BuiltIn InstanceId\n               2:             TypeVoid\n               3:  
           TypeFunction 2\n               6:             TypeFloat 32\n               7:             TypeVector 6(float) 2\n               8:             TypePointer Output 7(fvec2)\n  
         9(uv):      8(ptr) Variable Output\n              10:             TypePointer Input 7(fvec2)\n       11(uv_in):     10(ptr) Variable Input\n              13:             TypeVe
ctor 6(float) 4\n              14:             TypePointer Output 13(fvec4)\n 15(gl_Position):     14(ptr) Variable Output\n              16:             TypeMatrix 13(fvec4) 4\n       
       17:             TypePointer Input 16\n   18(transform):     17(ptr) Variable Input\n              20:             TypePointer Input 13(fvec4)\n    21(position):     20(ptr) Varia
ble Input\n              24:             TypeInt 32 1\n              25:             TypePointer Input 24(int)\n 26(gl_VertexID):     25(ptr) Variable Input\n27(gl_InstanceID):     25(p
tr) Variable Input\n         4(main):           2 Function None 3\n               5:             Label\n              12:    7(fvec2) Load 11(uv_in)\n                              Store
 9(uv) 12\n              19:          16 Load 18(transform)\n              22:   13(fvec4) Load 21(position)\n              23:   13(fvec4) MatrixTimesVector 19 22\n                    
          Store 15(gl_Position) 23\n                              Return\n                              FunctionEnd\n"
With diff:
@@ -1,13 +1,5 @@
-
-spv.test.vert
-WARNING: 0:5: attribute deprecated in version 130; may be removed in future release
-
-
-Linked vertex stage:
-
-
 // Module Version 10000
 // Generated by (magic number): 80001
-// Id's are bound by 24
+// Id's are bound by 28

                               Capability Shader
@@ -14,5 +6,5 @@
                1:             ExtInstImport  \"GLSL.std.450\"
                               MemoryModel Logical GLSL450
-                              EntryPoint Vertex 4  \"main\" 9 11 15 18 21
+                              EntryPoint Vertex 4  \"main\" 9 11 15 18 21 26 27
                               Source GLSL 140
                               Name 4  \"main\"
@@ +14,9 @@
                               Name 18  \"transform\"
                               Name 21  \"position\"
+                              Name 26  \"gl_VertexID\"
+                              Name 27  \"gl_InstanceID\"
                               Decorate 15(gl_Position) BuiltIn Position
+                              Decorate 26(gl_VertexID) BuiltIn VertexId
+                              Decorate 27(gl_InstanceID) BuiltIn InstanceId
                2:             TypeVoid
                3:             TypeFunction 2
@@ +35,8 @@
               20:             TypePointer Input 13(fvec4)
     21(position):     20(ptr) Variable Input
+              24:             TypeInt 32 1
+              25:             TypePointer Input 24(int)
+ 26(gl_VertexID):     25(ptr) Variable Input
+27(gl_InstanceID):     25(ptr) Variable Input
          4(main):           2 Function None 3
                5:             Label

[  FAILED  ] GlslangTest.VertexShader140 (47 ms)
[----------] 1 test from GlslangTest (47 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (47 ms total)
[  PASSED  ] 0 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] GlslangTest.VertexShader140

@antiagainst
Copy link
Contributor Author

@johnkslang The tests are copied exactly from the original test files. The expected outputs are also copied directly from baseResults/, only removing those warnings (from stderr, I think), which I don't think matters.

@antiagainst
Copy link
Contributor Author

@@ -47,6 +47,11 @@ CMake: The currently maintained and preferred way of building is through CMake.
In MSVC, after running CMake, you may need to use the Configuration Manager to
check the INSTALL project.

Glslang is migrating to the [Google Test](https://github.com/google/googletest)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"migrating to" might be a little strong.
How about "is adding the ability to test with "

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@dneto0
Copy link
Contributor

dneto0 commented Mar 5, 2016

-1 I like gtesting a lot, but I think this particular use makes the test and update flow worse.

I think moving the source and base result text into C++ source text makes for a bad update flow.
I think we should keep the source and base result files in the same places, but the test fixture (for this class of tests) should load the sets of files from disk. Also the test executable should have a mode for updating the base results, and there should probably be a build target to force an update of the base result files. (Note that the build is likely to be outside of the source tree, so you'll need an argument to know where the sources are.)

I'm all for gtesting, but the place it will add lots of value is for testing low level things, e.g. in the preprocessor. For example a fix for #29 could have unit test to ensure that the root cause (an underflow on an array index in the preprocessor) is resolved.

@antiagainst
Copy link
Contributor Author

@dneto0:

Totally agreed with using gtests to do unit test kind of thing for future tests.

But I have different thoughts on the update flow. It may be slightly worse to update than the current approach, but the problem is, we shouldn't keep adding new stuff to the existing tests. Instead we should create new test cases using gtest. Using files basically encourages (well, compared to using gtests) devs to just append things they want to check to existing files. So by "updating", it is supposed to only be bugfixing, which I assume will typically not trigger a dramatic output change. So copying from the gtest output and pasting it into the source shouldn't be a big burden. On the other side, we get the the benefits of fast loading (strings inside the program vs. opening files and reading), easy testing in out-of-source-build scenario (remember the pain we have in order to do clean out-of-source testing in shaderc?) better contrast (with input and expected output quite near each other, instead of traversing filesystem to open different files), etc. I think the benefits outweigh the loss in update flow.

Ideally, some of these large integration tests should be splitted into multiple minimal tests covering only one features to be tested. But as a introducing-new-test-framework thing, it would be difficult to review by doing that. So, next step maybe.

@xorgy
Copy link
Contributor

xorgy commented Mar 5, 2016

I figure we ought to load test inputs and outputs from files. It seems it would be annoying changing the test source code to run with different test data; especially given that they are plain strings.

@johnkslang
Copy link
Member

@antiagainst Wow, thanks. We definitely need a way to have lots more and smaller tests without running slower than the current suite.

We also need a fast and smooth workflow for

  1. running the tests
  2. analyzing the test changes
  3. replacing old results with new results

That can currently be done from the Test directory by

  1. runtests
  2. bump; git difftool
  3. git add/commit

Now, there are really two projects here, that have different histories and needs, and hence its possible the action to take WRT testing today might be different:

  • GLSL validator
  • SPIR-V generator

Note the differences between them:

GLSL validator

  • Khronos reference
  • grew (from 1.1) incrementally, with each change having a test change to reflect it and regression test it
  • sensitive to line-number changes
  • tests relatively complete (WRT to the code changes made; somewhat white box), and important to leave intact
  • it's largely about getting the right syntax/semantic errors

SPIR-V generator

  • leveraged a layer from another project
  • large part did not incrementally grow
  • tests are more a sanity check, from a collection of examples covering a range of functionality but not exhaustive
  • sensitive to id renaming
  • it's all about whether the generated code is valid and executes correctly

Main point: Growing a new fresh complete set of SPIR-V tests would be sensible and valuable, while not losing anything from the GLSL validator semantics tests is critical. SPIR-V generation is actually getting better testing, through execution, through the Khronos CTS suite execution on actual drivers.

So, the ideal thing to do for the validator might be different than the ideal thing to do for SPIR-V generation.

No matter what though, each test suite is subject to a change that can slightly effect almost all outputs, and after verifying the test results changes are okay, it should be trivial to mass update all the test results.

I suspect most performance issues are with creating multiple processes, and not with doing file I/O. So, I suspect there is a solution lurking that simultaneously achieves the following objectives:

  • tests can be much smaller and more focused on a specific feature or code path
  • corollary: there are lots more tests
  • tests can run as fast or faster than they currently do
  • workflow for updating a huge set of changes is as smooth/fast as it is today

Thanks for contributing to this!

@antiagainst antiagainst force-pushed the gtest branch 3 times, most recently from fa7a9be to 21e4875 Compare March 8, 2016 04:56
@antiagainst
Copy link
Contributor Author

Still WIP.

  • Changed the implementation to load input and expected output form files.
  • Will try to add a command-line flag like --update-mode which should write the real output to the file for expected output.

Example of running:

glslang/build - [gtest] » ninja && ./gtests/glslangtests
[2/2] Linking CXX executable gtests/glslangtests
[==========] Running 101 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 101 tests from Glsl/CompileToSpirvTest
[ RUN      ] Glsl/CompileToSpirvTest.FromFile/spv_do_simple_vert
[       OK ] Glsl/CompileToSpirvTest.FromFile/spv_do_simple_vert (62 ms)
[ RUN      ] Glsl/CompileToSpirvTest.FromFile/spv_do_while_continue_break_vert
[       OK ] Glsl/CompileToSpirvTest.FromFile/spv_do_while_continue_break_vert (60 ms)
[ RUN      ] Glsl/CompileToSpirvTest.FromFile/spv_for_complex_condition_vert
[       OK ] Glsl/CompileToSpirvTest.FromFile/spv_for_complex_condition_vert (78 ms)
[ RUN      ] Glsl/CompileToSpirvTest.FromFile/spv_for_continue_break_vert
[       OK ] Glsl/CompileToSpirvTest.FromFile/spv_for_continue_break_vert (61 ms)
[ RUN      ] Glsl/CompileToSpirvTest.FromFile/spv_for_simple_vert
[       OK ] Glsl/CompileToSpirvTest.FromFile/spv_for_simple_vert (60 ms)
[ RUN      ] Glsl/CompileToSpirvTest.FromFile/spv_for_notest_vert
[       OK ] Glsl/CompileToSpirvTest.FromFile/spv_for_notest_vert (77 ms)
[ RUN      ] Glsl/CompileToSpirvTest.FromFile/spv_for_nobody_vert
[       OK ] Glsl/CompileToSpirvTest.FromFile/spv_for_nobody_vert (77 ms)
[ omitted ]
[----------] 101 tests from Glsl/CompileToSpirvTest (5494 ms total)

[----------] Global test environment tear-down
[==========] 101 tests from 1 test case ran. (5494 ms total)
[  PASSED  ] 101 tests.

@antiagainst
Copy link
Contributor Author

@dneto0 @xorgy It makes sense for me now, thanks for the suggestion! I've converted to loading from files. :)

@johnkslang: Thanks for the great detailed explanation of the scopes and high-level thingy. Now I see the big picture more clearly. Yeah, it would be better to avoid touching the stable GLSL tests. Future SPIR-V tests and unit tests better go with gtest.
With the current implementation, the update workflow is the same as the previous (if errors, run the binary to generate the "true" expected, and git add/commit). I intended to add --update-mode to automate that process, tho.
For performance, I'll compare afterwards.

@xorgy
Copy link
Contributor

xorgy commented Mar 8, 2016

@antiagainst Looking great. :-)

@antiagainst
Copy link
Contributor Author

Added another patch to do real per process initialization. This significantly reduces time required to run tests. (See the commit msg for details.)

GlslangEnvironment() { glslang::InitializeProcess(); }
~GlslangEnvironment() { glslang::FinalizeProcess(); }
};
GlslangEnvironment environment;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Google style guide forbids variables of (non trivial) class type with static storage duration, due to concerns about indeterminate order of construction and destruction.
https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables

You can achieve the same thing by putting the initialization and finalization right into the main() function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some comments to explain why this happens.

@dneto0
Copy link
Contributor

dneto0 commented Mar 8, 2016

Looking pretty good. Thanks!
Two nits:

  • make data members private
  • avoid variables with static duration of non-trivial class type.

@mknejp
Copy link
Contributor

mknejp commented Mar 8, 2016

Has anyone taken a look at how Clang/LLVM do testing? Their test suite is pretty sophisticated. When it comes to Clang they have several stages of testing.

First there are usual unit tests, but they really just test classes and functions, they are just your average unit tests that don't touch any files.

Second Clang can run in verification mode with a hidden command line switch -verify. If active Clang records its own diagnostic output and compares it to what's written in the input. This is used mainly for negative testing, for example:

int x{2.f}; // expected-error {{narrowing conversion from 'float' to 'int'}}
int y = x; // expected-warning {{unused variable 'y'}}

At the end of the translation unit Clang checks that the diagnostics it created match what's written in the comments and if not the compilation fails with the appropriate error message indicating which tests failed. If all encountered errors match the expected errors the compilation is considered successful. -fsyntax-only makes sure no actual file output is generated.

And third, for positive testing they have a tool called FileCheck that they pipe the compiler output and input to to ensure the file has the expected content. For example

// RUN: glslangValidator -V -o - %s | FileCheck %s
void main()
{
// CHECK:     [[INT:%[0-9]+]] = OpTypeInt 32 0
// CHECK-DAG: [[ONE:%[0-9]+]] = OpConstant [[INT]] 1
// CHECK-DAG: [[TWO:%[0-9]+]] = OpConstant [[INT]] 2
// CHECK:     [[C:%[0-9]+]]   = OpVariable [[INT]] Function
// CHECK:     [[TMP:%[0-9]+]] = OpIAdd [[INT]] [[ONE]] [[TWO]]
// CHECK:                       OpStore [[C]] [[TMP]]
  int c = 1 + 2;
}

(The -o - option would output to stdout). This makes the test more focused on what it's actually translating regardless of all the boilerplate surrounding the interesting statement and it's robust against instruction reordering or varying IDs.

This is all obviously more work, even though the FileCheck tool already exists and could be borrowed from LLVM. I think the morale of this story is that the input and expected output are always in the same file for easier maintenance. They also support the same input be compiled several times with different options and the CHECK annotation is appropriately customized to apply only to a specific compiler invocation.

More details about FileCheck is here: http://llvm.org/docs/CommandGuide/FileCheck.html
I thought I'd mention this since they basically already solved the same problem and there's no point in reinventing the wheel.

@antiagainst
Copy link
Contributor Author

@mknejp: FileCheck is definitely a great tool for solving text-based flexible comparison. However, as @johnkslang mentioned previously, there are two projects involved in this codebase: one for GLSL validator and one for SPIR-V generator. I'm not sure adopting FileCheck for the former, which means to rewrite all the "stable" tests, is the way to go. And we want unit tests for the both projects. FileCheck cannot do that, but GTest can. Even if we use FileCheck for the SPIR-V generator, we still need to pull in GTest for unit testing. Now we have three testing harnesses, which is not quite optimal. Besides, FileCheck doesn't provide a smooth update workflow, I think.

By using GTest, we have the ability to grow future unit tests. And by hacking GTest a little bit, we can provide the same (or better) functionality than the runtests script, which will hopefully phase out the runtests script in the future and have a unified test framework.

But, yeah, this is just my thoughts. Definitely needs @johnkslang's expertise on this issue.

@mknejp
Copy link
Contributor

mknejp commented Mar 8, 2016

@antiagainst I'm not saing abandon unit tests, but use unit tests what they are meant for.

Right now, unless I am mistaken, we pretty much assume that the SPIR-V disassembler is error-free when doing the diff-based tests. What we really have to test is the actual binary produced by spv::Builder. So if going the unit test route, we should make sure all the classes in the spv namespace are doing what they are supposed to. Then we should ensure the SPIR-V disassembler does what it's supposed to and then can we reliably use diffs or tools like FileCheck to do convenient file-based testing on the output. I don't think gtest can do all of that and I'm not sure it should. Having multiple test harnesses is not a bad thing per se as long as they all serve a different purpose and are intuitive to use and change.

When it comes to the GLSL validator project I agree that FileCheck is of little use. That's why Clang has the -verify option to check its own diagnostics. But you can of course only rely on that working if you have unit tests for the diagnostics parsing, recording, and comparing.

Not sure what you mean by a lack of smooth update process. The FileCheck based process is you define the output you expect to be in the generated file and because these tests can be made much shorter and more focused than a full-blown SPIR-V dump they are much less sensitive to changes in instruction reordering or different counting of IDs or other generator changes. You can have one isolated test for every expression, statement or feature and make sure it generates the opcodes you want in the order you want/don't want. There shouldn't be much of an upgrade process, only adding new tests.

The way it is right now, whether with gtest or file diffs, if you change the order in which IDs are generated in SPIR-V you have to update all test files because suddenly the ID of OpEntryPoint is different in every single one of them. The tests are not isolated. A test should not fail because I changed something it is not testing. Worse, a human has to go over all those changed files and manually check that their semantics have not changed. That is very scary.

@antiagainst
Copy link
Contributor Author

@mknejp Sorry, I was reading too quickly and only focused on the latter parts of your arguments, so misunderstood your idea. I thought you were suggesting to use FileCheck instead of GTest. :)

This patch is to add GTest as a framework for future unit tests. And it would also be nice to have a better mechanism to replace the current runtests script (which has the problem of not playing well with out-of-source build, etc.) while keeping the tests we have now.

Unit testing part is not that controversial, so you see what I'm doing here, for the purpose of seeking feedback, is just providing a kinda hacky (yeah, I know and admit this) way of subsuming the responsibility of runtests. The Clang -verify mechanism and FileCheck are nice, but, because of my limited experience, I'm not sure how they can help with the second task without rewriting the existing tests.

The id-agnostic diff is a nice thing to have, and clearly FileCheck is a nice way to go, but that would be a different issue if we have the assumption of using different test harnesses to do what they are good at.

For the workflow thing, my previous discussion is also targeting at existing tests.

@dneto0
Copy link
Contributor

dneto0 commented Mar 8, 2016

@mknejp : I agree there's a lot more we can do to test glslang at various levels of granularity. Yes, I've worked with Clang and LLVM extensively, writing many tests for it and understand its benefits. They're great, but we don't have similar tools here (yet?).

This merge request is primarily about adding the ability to use gtest at all. Gtest really shines for unit tests, clearly. For example, once I can test with Gtest, I'd like to fix #29 but do it with confidence by adding unit tests.
All those other things you mention are great too, but could be contributed by someone in later pull requests.

@antiagainst antiagainst force-pushed the gtest branch 2 times, most recently from 081f82d to 72e8ab3 Compare March 9, 2016 17:42
@antiagainst
Copy link
Contributor Author

@johnkslang:

  1. The inclusion of Google Test is protected by checks in CMake (see External/CMakeLists.txt & gtests/CMakeLists.txt). If no Google Test is provided (either by a project including both glslang and GTest or by putting GTest code in External/), the whole GTest related thing won't build at all. So should be fine for glslang clients who won't want to support this.
  2. Yes. GTest naturally support unit tests. And I've also added necessary functionalities to provide a test "harness" (based on GTest) that can read input and expected output from the existing test files like the runtests script. Adding new integration tests is as easy as before, just drop the input, expected output into the correct directories, and then add the test name into the big lists in gtests/*.FromFile.cpp. And the new "harness" runs much faster (initialization is done per gtest file, not per shader test anymore), plays well with out-of-source-build-and-test scenario, etc. Besides, with the --update-mode, updating is also as trivial as just appending a command-line option (well, after examining the real output is sane).
  3. The test files won't need to be updated at all. But some more utility functions need to be written to wrap more existing tests. And I'll do that.

But now this is just a demo of concept (for seeking feedback before I go too far) and only tested out on Linux. So please just wait a minute, I'll go and test this out on Windows and makes sure it works fine. ;) (Line endings, etc. could be a problem when comparing results.)

Well let you know when I think it's ready. Thanks!

@antiagainst
Copy link
Contributor Author

@johnkslang:

Ready to be merged right now. :)

How to try out: place a copy of GTest under External/, reconfigure, & rebuild. then run ctest or, the glslangtests binary in <build-dir>/gtests.

How to update expected output with real output: run the glslangtests binary in <build-dir>/gtests with --update-mode. Note: only preprocessor and spirv tests are included now, so changing other tests won't work.

@AWoloszyn
Copy link
Contributor

For the record I just tested this change versus runtests for just the spirv/preprocessor tests and got the following results for speed:

runtests: (only running spv and preprocessor tests)
real 0m35.235s
user 0m1.671s
sys 0m15.647s

glslangtests.exe (only the spv and preprocessor tests)
[----------] Global test environment tear-down
[==========] 116 tests from 2 test cases ran. (2289 ms total)
[ PASSED ] 116 tests.

so around a 17x speed increase on Windows for the change.

@johnkslang
Copy link
Member

Awesome. Reusing symbol tables and processes is a big win, of course, as is not having a shell script forking a bunch of commands.

The script was also testing parallel compiles: it compiled a bunch of shaders multithreaded to test for issues there, and that ran similarly fast.

We won't want to lose that thread testing, BTW.

@antiagainst
Copy link
Contributor Author

8d380b8 adds a unit test for one of the newly added functions. :)

@antiagainst
Copy link
Contributor Author

Hi @johnkslang, the code is ready to be merged now.

Tried on Windows with VS 14 2015 & MSVC 19.0.23506.0. Built & Tested cleanly.

@johnkslang
Copy link
Member

Do we know about VS 2013? We keep adjusting for 2010 in the core (required) code base, but I think it's okay if 2010 can't the extended (optional, gtest) code base. As a middle ground, I run and test frequently on 2013, and think many do, so it would be desirable for 2013 to work.

@AWoloszyn
Copy link
Contributor

I ran this, at least at the time of my last comment, on VS2013 and everything worked.

@dekimir
Copy link

dekimir commented Mar 11, 2016

We just verified the latest version of this PR on VS2013:

-- The C compiler identification is MSVC 18.0.31101.0
-- The CXX compiler identification is MSVC 18.0.31101.0

@antiagainst
Copy link
Contributor Author

Hi @johnkslang, how do you think about the current implementation?

"spv.specConstant.vert",
"spv.specConstant.comp",
// GLSL-level semantics
"vulkan.frag",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note the spv.* tests are expected to compile without error, so they can go all the way through to SPIR-V without error, while most other tests, including vulkan.* tests are testing the semantics of the front-end, expected to get the right set of errors without going through to SPIR-V.

I'm unclear yet on which list then you want the vulkan.* tests in; this one or the earlier one. Or, a separate one. It does seem a bit inconsistent here, as they are the only ones in this list that need their error messages checked, rather than expected to get no errors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, previously I didn't notice there are such differences: just did a bindly copy-pasta of the Test/test-spirv-list file. ;)

The way how these in-file tests are loaded, compiled, and then checked is coded via LoadFileCompileAndCheck() & CompileGlsl(). Basically, it just mimics how the standalone glslangValidator goes: compiling and linking shaders, and concatenating InfoLog and DebugInfoLog from both compiling and linking and comparing them with golden files. So no matter whether errors are expected or not, the procedure is the same.

To check different output channels for different existing in-file tests, I believe the expected result files need to be modified to remove the output from other channels; but that will cause problem with the runtests script when running multiple-threaded tests. (One of the purpose is to handle the responsibility of single-threaded tests from the runtests script to GTests, but not multiple-threaded tests for now.)

I did a rebase against master with a new commit a80673a, in which a separate template is created for the vulkan.* tests to discriminate them.


${CMAKE_CURRENT_SOURCE_DIR}/Spv.General.cpp

${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for main.cpp -- use gtest_main target like in shaderc/cmake/utils.cmake:7.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But we need an extra cloption --update-mode, which is added in main.cpp.

@antiagainst antiagainst force-pushed the gtest branch 2 times, most recently from 3d4dbfb to af6e729 Compare March 22, 2016 18:20
@xorgy
Copy link
Contributor

xorgy commented Mar 23, 2016

Looks like things are essentially ready, just need to squash+rebase the commits and do a final review. :-)

The existing test harness is a homemade shell script. All the tests
and the expected results are written in plain text files. The harness
just reads in a test, invoke the glslangValidator binary on it, and
compare the result with the golden file. All tests are kinda
integration tests.

This patch add Google Test as an external project, which provides a
new harness for reading shader source files, compile to SPIR-V, and
then compare with the expected output.
@antiagainst
Copy link
Contributor Author

Hi @johnkslang, the code is squashed and rebased. Ready to go in now. Thanks!

@johnkslang johnkslang merged commit a42533e into KhronosGroup:master Mar 31, 2016
@antiagainst antiagainst deleted the gtest branch March 31, 2016 19:16
qingyuanzNV pushed a commit to qingyuanzNV/glslang that referenced this pull request Oct 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants