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

WebGL stub for unit tests #4827

Merged
merged 88 commits into from
Jan 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
c0f8776
Start of expectRenderForSpecs and friends
pjcozzi Dec 1, 2016
4912f49
Start of webglstub parameter
pjcozzi Dec 1, 2016
1b16385
Start of WebGL stub
pjcozzi Dec 1, 2016
c1f320c
Remove unused code
pjcozzi Dec 2, 2016
9c54cb3
WIP WebGL stubs. Viewer/Sandcastle run and SceneSpec passes.
pjcozzi Dec 2, 2016
547d126
Pass through webglStub query parameter
pjcozzi Dec 2, 2016
580f379
Improve stub expect functions
pjcozzi Dec 12, 2016
95feba7
Update Scene tests to new expectation stubs
pjcozzi Dec 12, 2016
8a220bd
Update Model tests to use scene stub
pjcozzi Dec 12, 2016
a75b7b9
Merge remote-tracking branch 'origin/master' into webgl-mock-for-tests
pjcozzi Dec 12, 2016
49b13ad
Replace custom Scene expectation functions with custom Jasmine matchers
pjcozzi Dec 13, 2016
70e20ef
Update Model and Scene specs to use new custom Jasmine matchers
pjcozzi Dec 13, 2016
2737775
Merge remote-tracking branch 'origin/master' into webgl-mock-for-tests
pjcozzi Dec 13, 2016
c21e1d9
Update DebugModelMatrixPrimitive specs to use WebGL stub
pjcozzi Dec 13, 2016
aac0794
Rename toPick to toPickAndCall to match toRenderAndCall
pjcozzi Dec 13, 2016
f6077b8
Pass in time as part of the actual, not expected, value
pjcozzi Dec 13, 2016
fda3a20
Update Billboard, Label, and Point collection tests to use WebGL stub
pjcozzi Dec 13, 2016
461104f
Update moon and sky tests
pjcozzi Dec 13, 2016
42cd0d6
Update shadow map tests to use WebGL stubs
pjcozzi Dec 13, 2016
e1d1def
Make toRender and toRenderAndCall consistent
pjcozzi Dec 13, 2016
1bf523e
Update more tests to use new WebGL stubs
pjcozzi Dec 14, 2016
6ca7cc7
Merge remote-tracking branch 'origin/master' into webgl-mock-for-tests
pjcozzi Dec 14, 2016
f8e7ffa
Fix JSHint warnings
pjcozzi Dec 14, 2016
08d3768
Fix custom matchers so scene.render and scene.pick are called in all …
pjcozzi Dec 15, 2016
f23ef60
Update Primitive, Polyline, and Apperance tests to use WebGL stub
pjcozzi Dec 15, 2016
caeb229
Fix PrimitiveCollection picking tests
pjcozzi Dec 15, 2016
72b8783
New toPickPrimitive custom matcher
pjcozzi Dec 15, 2016
cf9bb81
Convert the rest of the tests in Scene to use the WebGL stub
pjcozzi Dec 15, 2016
b31303b
Remove old pickForSpecs
pjcozzi Dec 15, 2016
fd224b9
Added toDrillPickAndCall custom matcher
pjcozzi Dec 15, 2016
ba5a5eb
Merge master to webgl-mock-for-tests
pjcozzi Dec 15, 2016
fb2af93
renderForSpecs no longer needs to readPixels
pjcozzi Dec 16, 2016
4bc0ec1
Replace verifyDrawForSpecs with custom matcher
pjcozzi Dec 16, 2016
c54bfba
Custom matchers for readPixels
pjcozzi Dec 16, 2016
f252fbb
Replace renderFragment with custom matcher
pjcozzi Dec 19, 2016
46c2cb6
Update Context tests to use custom matchers
pjcozzi Dec 19, 2016
3a8d570
Update some shader program tests to use custom matchers
pjcozzi Dec 19, 2016
bd0ccf2
Merge remote-tracking branch 'origin/master' into webgl-mock-for-tests
pjcozzi Dec 19, 2016
f629023
Merge remote-tracking branch 'origin/master' into webgl-mock-for-tests
pjcozzi Dec 19, 2016
c7e547b
Update Texture specs to use WebGL stub
pjcozzi Dec 20, 2016
7c2c36e
Update cube map specs to use WebGL stubs
pjcozzi Dec 20, 2016
fc9459f
Fix JSHint warnings
pjcozzi Dec 20, 2016
28012ba
Merge remote-tracking branch 'origin/master' into webgl-mock-for-tests
pjcozzi Dec 20, 2016
12d59ec
Fix failing tests
pjcozzi Dec 20, 2016
8af301e
Merge remote-tracking branch 'origin/master' into webgl-mock-for-tests
pjcozzi Dec 21, 2016
c988bfd
Update Draw specs to use WebGL stub
pjcozzi Dec 21, 2016
e68ef29
Rename to contextToRender
pjcozzi Dec 21, 2016
4c42e52
Update Framebuffer specs to use WebGL stub
pjcozzi Dec 21, 2016
993ae8b
Update TextureAtlas specs to use WebGL stub
pjcozzi Dec 21, 2016
0317330
Change createContext and related tests to not request alpha for the W…
pjcozzi Dec 21, 2016
282d75f
Clean up vertex attribute locations in tests
pjcozzi Dec 21, 2016
5224f92
Clean up part of Framebuffer specs using WebGL stub
pjcozzi Dec 21, 2016
a6c4303
All Renderer tests now pass with WebGL stub
pjcozzi Dec 21, 2016
2e5c540
Update tests that require ground primitive support
pjcozzi Jan 5, 2017
0d56eb9
Merge remote-tracking branch 'origin/master' into webgl-mock-for-tests
pjcozzi Jan 5, 2017
937fc23
Fix timing issue when using WebGL stub from the command line
pjcozzi Jan 5, 2017
f49298b
Replace non-WebGL tests with WebGL stub tests when running CI
pjcozzi Jan 5, 2017
8f41266
Use WebGL stubs in Viewer tests
pjcozzi Jan 5, 2017
a211783
Remove destroyCanvas
pjcozzi Jan 5, 2017
ed1d591
Use WebGL stub with widget tests
pjcozzi Jan 5, 2017
2ae74bf
Fix JSHint warnings
pjcozzi Jan 5, 2017
5205fce
Move WebGL stub to the Specs directory so it is not part of the Cesiu…
pjcozzi Jan 5, 2017
4bcce0d
Run with WebGL stub on CI for real
pjcozzi Jan 5, 2017
4b4527e
Fix Primitive test for CI
pjcozzi Jan 6, 2017
7cd809b
Fix CV bounding sphere test
pjcozzi Jan 6, 2017
297674e
Merge remote-tracking branch 'origin/master' into webgl-mock-for-tests
pjcozzi Jan 6, 2017
d55154a
Workaround so tests pass when ran from the command line
pjcozzi Jan 6, 2017
d62a572
Fix tests when ran in release with debug code removed
pjcozzi Jan 6, 2017
32fdda5
Fix syntax error
pjcozzi Jan 6, 2017
900079a
Fix some release tests when ran from the command-line for CI
pjcozzi Jan 6, 2017
4fae8ad
Merge remote-tracking branch 'origin/master' into webgl-mock-for-tests
pjcozzi Jan 6, 2017
396682c
Add custom rendering expectations to Testing Guide
pjcozzi Jan 9, 2017
1f3584a
Testing Guide copyedits
pjcozzi Jan 9, 2017
d7d6ab9
Re-enable spec that passes with WebGL stub now
pjcozzi Jan 9, 2017
4e13c5f
Merge remote-tracking branch 'origin/master' into webgl-mock-for-tests
pjcozzi Jan 10, 2017
edef251
Merge master to webgl-mock-for-tests
pjcozzi Jan 10, 2017
8474c48
Merge remote-tracking branch 'origin/master' into webgl-mock-for-tests
pjcozzi Jan 10, 2017
f5ef72d
Merge remote-tracking branch 'origin/master' into webgl-mock-for-tests
pjcozzi Jan 11, 2017
7ef5df6
Merge remote-tracking branch 'origin/master' into webgl-mock-for-tests
pjcozzi Jan 13, 2017
3e33ad5
Cleanup
lilleyse Jan 23, 2017
a588cc3
Merge remote-tracking branch 'origin/master' into webgl-mock-for-tests
pjcozzi Jan 27, 2017
35658d0
Update test to use contextToRender
pjcozzi Jan 27, 2017
95592a6
Add testing with WebGL stubs to the Build Guide
pjcozzi Jan 27, 2017
f3c37a7
Remove test workaround
pjcozzi Jan 27, 2017
bf7518a
Tweak Testing Guide
pjcozzi Jan 27, 2017
7d433c4
Changes based on review
pjcozzi Jan 27, 2017
ba49da8
Fix JSHint warnings
pjcozzi Jan 27, 2017
557d6ab
Updates based on review
pjcozzi Jan 27, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ script:
- npm run jsHint -- --failTaskOnError
- echo -en 'travis_fold:end:script.jsHint\\r'

- echo 'test non-webgl' && echo -en 'travis_fold:start:script.test\\r'
- npm run test -- --exclude WebGL --browsers Electron --failTaskOnError --suppressPassed
- echo 'test webgl-stub' && echo -en 'travis_fold:start:script.test\\r'
- npm run test -- --browsers Electron --webgl-stub --failTaskOnError --suppressPassed
- echo -en 'travis_fold:end:script.test\\r'

- echo 'makeZipFile' && echo -en 'travis_fold:start:script.makeZipFile\\r'
Expand All @@ -30,8 +30,8 @@ script:
- npm run deploy-status -- --status success --message Deployed
- echo -en 'travis_fold:end:script.deploy\\r'

- echo 'test non-webgl release' && echo -en 'travis_fold:start:script test.release\\r'
- npm run test -- --exclude WebGL --browsers Electron --failTaskOnError --release --suppressPassed
- echo 'test webgl-stub release' && echo -en 'travis_fold:start:script test.release\\r'
- npm run test -- --browsers Electron --failTaskOnError --webgl-stub --release --suppressPassed
- echo -en 'travis_fold:end:script test.release\\r'

- echo 'cloc' && echo -en 'travis_fold:start:script.cloc\\r'
Expand Down
7 changes: 4 additions & 3 deletions Documentation/Contributors/BuildGuide/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,11 @@ Here's the full set of scripts and what they do.
* **Testing scripts** -- build and run the unit tests
* `test` - Runs all tests with [Karma](http://karma-runner.github.io/0.13/index.html) using the default browser specified in the Karma config file.
* `test-all` - Runs all tests with Karma using all browsers installed on the current system.
* `test-non-webgl` - Runs only non-WebGL tests with Karma.
* `test-webgl` - Runs only WebGL tests with Karma.
* `test-non-webgl` - Runs only non-WebGL tests.
* `test-webgl` - Runs only WebGL tests.
* `test-webgl-stub` - Runs all tests using the WebGL stub, which WebGL calls a noop and ignores related test expectations.
* `test-webgl-validation` - Runs all tests with Karma and enables low-level WebGL validation.
* `test-release` - Runs all tests with Karma on the minified release version of built Cesium.
* `test-release` - Runs all tests on the minified release version of built Cesium.
* **Deployment scripts**
* `deploy-s3` - Deploys the built cesium files, the npm package, and the zip file to Amazon S3. This requires having credentials set up for the S3 bucket to which you are deploying.
* `deploy-status` - Set the deployment statuses in GitHub, for use with Travis.
Expand Down
131 changes: 111 additions & 20 deletions Documentation/Contributors/TestingGuide/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ As of Cesium 1.15, Cesium has over 7,000 tests with 93% code coverage. Cesium h
All new code should have 100% code coverage and should pass all tests. Always run the tests before opening a pull request.

* [Running the Tests](#running-the-tests)
* [Run All Tests (Run with WebGL Validation)](#run-all-tests-run-with-webgl-validation)
* [Run All Tests](#run-all-tests)
* [Run with WebGL validation](#run-with-webgl-validation)
* [Run with WebGL stub](#run-with-webgl-stub)
* [Select a Test to Run](#select-a-test-to-run)
* [Run Only WebGL Tests](#run-only-webgl-tests)
* [Run Only Non-WebGL Tests](#run-only-non-webgl-tests)
* [Run All Tests against Combined File (Run All Tests against Combined File with Debug Code Removed)]()
* [Run All Tests with Code Coverage (Build 'instrumentForCoverage' First)](#run-all-tests-against-combined-file-run-all-tests-against-combined-file-with-debug-code-removed)
* [Run All Tests on the Command Line with Karma](#run-all-tests-on-the-command-line-with-karma)
* [Running Tests on the Command Line with Karma](#run-all-tests-on-the-command-line-with-karma)
* [Testing Previous Versions of Cesium](#testing-previous-versions-of-cesium)
* [`testfailure` Label for Issues](#testfailure-label-for-issues)
* [Writing Tests](#writing-tests)
Expand Down Expand Up @@ -44,7 +46,7 @@ The Cesium tests are written in JavaScript and use [Jasmine](http://jasmine.gith

When running Cesium locally, browse to [http://localhost:8080/](http://localhost:8080/) and there are several test options:

### Run All Tests (Run with WebGL Validation)
### Run All Tests

Runs all the tests. As of Cesium 1.15, on a decent laptop, they run in about a minute in Chrome. It is important that the tests run quickly so we run them often.

Expand All @@ -62,8 +64,14 @@ In this case, the number of failing tests is listed at the top, and details on e
```
Click on the failed test to rerun just that test. This is useful for saving time when fixing an issue as it avoids rerunning all the tests. Always rerun _all_ the tests before opening a pull request.

#### Run with WebGL validation

The link to **Run with WebGL validation** passes a query parameter to the tests to enable extra low-level WebGL validation such as calling `gl.getError()` after each WebGL call. We use this when doing the monthly Cesium release and when making changes to Cesium's renderer.

#### Run with WebGL stub

The **Run with WebGL stub** link passes a query parameter to the tests to use Cesium's WebGL stub. This makes all WebGL calls a noop and ignores test expectations that rely on reading back from WebGL. This allows running the tests on CI where a reasonable WebGL implementation is not available and still getting full code coverage albeit not all verification.

### Select a Test to Run

This option loads the test page without running any tests.
Expand Down Expand Up @@ -140,7 +148,7 @@ It is possible to have 100% code coverage with two tests: one test where `a` and

The number of linearly independent paths (four in this case) is called the **cyclomatic complexity**. Be mindful of this when writing tests. On one extreme, 100% code coverage is the least amount of testing, on the other extreme is covering the cyclomatic complexity, which quickly becomes unreasonable. Use your knowledge of the implementation to devise the best strategy.

### Run All Tests on the Command Line with Karma
### Running Tests on the Command Line with Karma

[Karma](http://karma-runner.github.io/0.13/index.html) is a tool which spawns a browser window, runs tests against that browser, and displays the results on the command line.

Expand All @@ -166,6 +174,10 @@ It is also possible for Karma to run all tests against each browser installed on

`npm run test-webgl-validation`

#### Run All Tests with WebGL Stub

`npm run test-webgl-stub`

#### Run Only WebGL Tests with Karma

`npm run test-webgl`
Expand Down Expand Up @@ -317,7 +329,7 @@ Above, `scene` is scoped at the suite-level, so all tests in the file have acces
```javascript
it('renders', function() {
var p = scene.primitives.add(new DebugModelMatrixPrimitive());
expect(scene.renderForSpecs()).not.toEqual([0, 0, 0, 255]);
expect(scene).notToRender([0, 0, 0, 255]);
});
```

Expand All @@ -331,40 +343,119 @@ The tests in the `'WebGL'` category do not strictly follow this pattern. Creati

Unlike the `Cartesian3` tests we first saw, many tests need to construct the main Cesium `Viewer` widget or one of its major components. Low-level renderer tests construct just `Context` (which, itself, has a canvas and WebGL context), and primitive tests construct a `Scene` (which contains a `Context`).

As shown above, these tests use Cesium test utility functions: `createViewer`, `createScene`, or `createContext`. These functions honor query parameters passed to the tests (e.g., enabling WebGL validation) and add extra test functions to the returned object.
As shown above, these tests use Cesium test utility functions: `createViewer`, `createScene`, or `createContext`. These functions honor query parameters passed to the tests (e.g., enabling WebGL validation or the WebGL stub) and add a few utility functions to the returned object. For example, `createScene` creates a 1x1 pixel canvas with a Cesium Scene and adds `renderForSpecs` (to initialize and render a frame) and `destroyForSpecs` to the returned `Scene` object.

For example, `createScene` creates a 1x1 pixel canvas with a Cesium Scene and adds `renderForSpecs` and `pickForSpecs` to the returned `Scene` object:
> Most Cesium apps do not render the scene directly; instead, the `Viewer` object's default render loop renders the scene implicit to the user. The tests are an exception; most tests explicitly render the scene.

Cesium adds several custom Jasmine matchers to make the rendering tests more concise and to support running tests with the WebGL stub. When using the WebGL stub, the WebGL implementation is a noop, and test expectations that rely on reading back from WebGL are ignored. The rendering custom matchers are:

* `toRender`
* `notToRender`
* `toRenderAndCall`
* `toPickPrimitive`
* `notToPick`
* `toPickAndCall`
* `toDrillPickAndCall`
* `toReadPixels`
* `notToReadPixels`
* `contextToRender`
* `notContextToRender`

`toRender` and `notToRender` clear a 1x1 viewport to black, renders the scene into it, and verifies the RGBA value of the pixel, e.g.:

```javascript
it('renders', function() {
var p = scene.primitives.add(new DebugModelMatrixPrimitive());
expect(scene.renderForSpecs()).not.toEqual([0, 0, 0, 255]);
expect(scene).notToRender([0, 0, 0, 255]);
});

it('does not render when show is false', function() {
scene.primitives.add(new DebugModelMatrixPrimitive({
show : false
}));
expect(scene.renderForSpecs()).toEqual([0, 0, 0, 255]);
expect(scene).toRender([0, 0, 0, 255]);
});
```

it('is picked', function() {
var p = scene.primitives.add(new DebugModelMatrixPrimitive({
id : 'id'
}));
Like most rendering tests, the first example uses a coarse-grained expectation to check that the pixel is not the default value of black. Although an expectation this coarse-grained may not catch all subtle errors, it is reliable across platforms, and we rarely have bugs a more fine-grained test would have caught, especially with some manual testing (see below).

var pick = scene.pickForSpecs();
expect(pick.primitive).toEqual(p);
expect(pick.id).toEqual('id');
The second test verifies that the pixel value is the same as the default background color since the primitive's `show` property is `false`.

`toRender` and `notToRender` can also render the scene at a given Cesium simulation time, e.g.,:

```javascript
expect({
scene : scene,
time : t
}).toRender([0, 0, 0, 255]);
```

For more complicated expectations, which will still be ignored with the WebGL stub, `toRenderAndCall` takes a callback function:

```javascript
expect(scene).toRenderAndCall(function(rgba) {
expect(rgba[0]).not.toEqual(0);
expect(rgba[1]).toBeGreaterThanOrEqualTo(0);
expect(rgba[2]).toBeGreaterThanOrEqualTo(0);
expect(rgba[3]).toEqual(255);
});
```
In the first test, `renderForSpecs` initializes the frame, renders the scene into the 1x1 canvas, and then returns the RGBA value of the rendered pixel. Like most rendering tests, this uses a coarse-grained expectation to check that the pixel is not the default value of black. Although an expectation this coarse-grained may not catch all subtle errors, it is reliable across platforms, and we rarely have bugs a more fine-grained test would have caught, especially with some manual testing (see below).

In the second test, `renderForSpecs` is used again, but this time it is to verify that the pixel value is the same as the default background color since the primitive's `show` property is `false`.
For reliability across WebGL implementations, use complex expectations in `toRenderAndCall` sparingly.

> Most Cesium apps do not render the scene directly; instead, the `Viewer` object's default render loop renders the scene implicit to the user. The tests are an exception; most tests explicitly render the scene.
Similar custom matchers are used for picking tests:

```javascript
var b = billboards.add(/* ... */);
expect(scene).toPickPrimitive(b); // Can also use toPickAndCall() and toDrillPickAndCall()

b.show = false;
expect(scene).notToPick();
```

For tests that render the scene themselves, `toReadPixels` and `notToReadPixels` are used to verify the RGBA value. In the simplest case, pass an RGBA array, e.g.:

```javascript
expect(context).toReadPixels([0, 0, 0, 255]);

expect(context).notToReadPixels([0, 0, 0, 255]);
```

`toReadPixels` can also read from a given framebuffer and use an epsilon for the RGBA comparison test, e.g.:

```javascript
expect({
context : context,
framebuffer : framebuffer,
epsilon : 1
}).toReadPixels([0, 0, 0, 255]);
```

Low-level Cesium renderer tests use just a `Context` without a Cesium `Scene`, and use the `contextToRender` and `notContextToRender` custom matchers to render a WebGL point primitive to the context's 1x1 viewport and verify the RGBA value, e.g.:

In the final test, `pickForSpecs` executes a `Scene.pick` for the one-pixel canvas. A typical follow-up expectation verifies that the primitive of interest was picked and its `id` is the expected value.
```javascript
expect({
context : context,
shaderProgram : sp,
}).contextToRender(expected);

expect(/* ... */).notContextToRender();
```

Uniforms, the model matrix, and various depth options can be provided. In addition, instead of providing a full shader program, just the fragment shader's source can be provided, e.g.,

```javascript
it('can declare automatic uniforms', function() {
var fs =
'void main() { ' +
' gl_FragColor = vec4((czm_viewport.x == 0.0) && (czm_viewport.y == 0.0) && (czm_viewport.z == 1.0) && (czm_viewport.w == 1.0)); ' +
'}';
expect({
context : context,
fragmentShader : fs
}).contextToRender();
});
```

### GLSL

Expand Down
5 changes: 4 additions & 1 deletion Source/Core/WebGLConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,10 @@ define([
COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : 0x9279,
TEXTURE_IMMUTABLE_FORMAT : 0x912F,
MAX_ELEMENT_INDEX : 0x8D6B,
TEXTURE_IMMUTABLE_LEVELS : 0x82DF
TEXTURE_IMMUTABLE_LEVELS : 0x82DF,

// Extensions
MAX_TEXTURE_MAX_ANISOTROPY_EXT : 0x84FF
};

return freezeObject(WebGLConstants);
Expand Down
Loading