diff options
author | Tim Burke <tim.burke@gmail.com> | 2018-01-11 16:24:24 -0800 |
---|---|---|
committer | Tim Burke <tim.burke@gmail.com> | 2021-03-01 10:09:03 -0800 |
commit | c5152ed4d3a37c5e0017be9f0445bf0868561b96 (patch) | |
tree | 0e7dc25d05978bc88ba99659868861d155693c73 /test/cors/test-container.js | |
parent | 5c3eb488f2df5a93a9899a406fc9a4658efb272b (diff) | |
download | swift-c5152ed4d3a37c5e0017be9f0445bf0868561b96.tar.gz |
Add some functional CORS tests
If you've got selenium installed (and working), the whole thing can be
automated pretty well; run main.py, wait while some windows pop up (or
use xvfb-run to run things on a virtual display), then check out what
tests were run on which browsers and whether any of them failed. Exit
code is the number of failed tests.
Includes tests against:
- Account
- Containers, with various ACLs/CORS settings
- Objects
- /info
- SLOs
- DLOs
- Symlinks
Include a gate job that runs the tests in firefox.
Areas for future work:
- Install chromium and chromedriver in the gate; tests should
automatically pick up on the fact that it's available
- Capture the web browser's console logs, too, so we can get
more info when things go wrong
Change-Id: Ic1d3a062419f1133c6e2f00a598867d567358c9f
Diffstat (limited to 'test/cors/test-container.js')
-rw-r--r-- | test/cors/test-container.js | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/test/cors/test-container.js b/test/cors/test-container.js new file mode 100644 index 000000000..561d5f273 --- /dev/null +++ b/test/cors/test-container.js @@ -0,0 +1,148 @@ +import { + runTests, + MakeRequest, + HasStatus, + HasHeaders, + HasCommonResponseHeaders, + HasNoBody +} from './harness.js' + +function CheckJsonListing (resp) { + HasHeaders({ 'Content-Type': 'application/json; charset=utf-8' })(resp) + const listing = JSON.parse(resp.responseText) + for (const item of listing) { + if ('subdir' in item) { + if (Object.keys(item).length !== 1) { + throw new Error('Expected subdir to be the only key, got ' + JSON.stringify(item)) + } + continue + } + const missing = ['name', 'bytes', 'content_type', 'hash', 'last_modified'].filter((key) => !(key in item)) + if (missing.length) { + throw new Error('Listing item is missing expected keys ' + JSON.stringify(missing) + '; got ' + JSON.stringify(item)) + } + } + return listing +} + +function HasStatus200Or204 (resp) { + if (resp.status === 200) { + // NB: some browsers (like chrome) may serve HEADs from cached GETs, leading to the 200 + HasStatus(200, 'OK')(resp) + } else { + HasStatus(204, 'No Content')(resp) + } + return resp +} + +const expectedListing = [ + 'dlo', + 'dlo-with-unlistable-segments', + 'dlo/seg00', + 'dlo/seg01', + 'dlo/seg02', + 'dlo/seg03', + 'dlo/seg04', + 'dlo/seg05', + 'dlo/seg06', + 'dlo/seg07', + 'dlo/seg08', + 'dlo/seg09', + 'obj', + 'slo', + 'symlink-to-private', + 'symlink-to-public-no-cors', + 'symlink-to-public-with-cors' +] +const expectedWithDelimiter = [ + 'dlo', + 'dlo-with-unlistable-segments', + 'dlo/', + 'obj', + 'slo', + 'symlink-to-private', + 'symlink-to-public-no-cors', + 'symlink-to-public-with-cors' +] + +runTests('container', [ + ['GET format=txt', + () => MakeRequest('GET', 'public-with-cors', {}, '', {'format': 'txt'}) + .then(HasStatus(200, 'OK')) + .then(HasCommonResponseHeaders) + .then(HasHeaders({ 'Content-Type': 'text/plain; charset=utf-8' })) + .then((resp) => { + const names = resp.responseText.split('\n') + if (!(names.length === expectedListing.length + 1 && names.every((name, i) => name === (i === expectedListing.length ? '' : expectedListing[i])))) { + throw new Error('Expected listing to have items ' + JSON.stringify(expectedListing) + '; got ' + JSON.stringify(names)) + } + })], + ['GET format=json', + () => MakeRequest('GET', 'public-with-cors', {}, '', {'format': 'json'}) + .then(HasStatus(200, 'OK')) + .then(HasCommonResponseHeaders) + .then(CheckJsonListing) + .then((listing) => { + const names = listing.map((item) => 'subdir' in item ? item.subdir : item.name) + if (!(names.length === expectedListing.length && names.every((name, i) => expectedListing[i] === name))) { + throw new Error('Expected listing to have items ' + JSON.stringify(expectedListing) + '; got ' + JSON.stringify(names)) + } + })], + ['GET format=json&delimiter=/', + () => MakeRequest('GET', 'public-with-cors', {}, '', {'format': 'json', 'delimiter': '/'}) + .then(HasStatus(200, 'OK')) + .then(HasCommonResponseHeaders) + .then(CheckJsonListing) + .then((listing) => { + const names = listing.map((item) => 'subdir' in item ? item.subdir : item.name) + if (!(names.length === expectedWithDelimiter.length && names.every((name, i) => expectedWithDelimiter[i] === name))) { + throw new Error('Expected listing to have items ' + JSON.stringify(expectedWithDelimiter) + '; got ' + JSON.stringify(names)) + } + })], + ['GET format=xml', + () => MakeRequest('GET', 'public-with-cors', {}, '', {'format': 'xml'}) + .then(HasStatus(200, 'OK')) + .then(HasHeaders({ 'Content-Type': 'application/xml; charset=utf-8' })) + .then((resp) => { + const prefix = '<?xml version="1.0" encoding="UTF-8"?>\n<container name="public-with-cors">' + if (resp.responseText.substr(0, prefix.length) !== prefix) { + throw new Error('Expected response to start with ' + JSON.stringify(prefix) + '; got ' + resp.responseText) + } + })], + ['GET Accept: json', + () => MakeRequest('GET', 'public-with-cors', { Accept: 'application/json' }) + .then(HasStatus(200, 'OK')) + .then(HasCommonResponseHeaders) + .then(CheckJsonListing) + .then((listing) => { + if (listing.length !== 17) { + throw new Error('Expected exactly 17 items in listing; got ' + listing.length) + } + })], + ['GET Accept: xml', + // NB: flakey on Safari -- sometimes it serves JSON from cache, *even with* a Vary: Accept header + () => MakeRequest('GET', 'public-with-cors', { Accept: 'application/xml' }) + .then(HasStatus(200, 'OK')) + .then(HasHeaders({ 'Content-Type': 'application/xml; charset=utf-8' })) + .then((resp) => { + const prefix = '<?xml version="1.0" encoding="UTF-8"?>\n<container name="public-with-cors">' + if (resp.responseText.substr(0, prefix.length) !== prefix) { + throw new Error('Expected response to start with ' + JSON.stringify(prefix) + '; got ' + resp.responseText) + } + })], + ['HEAD format=txt', + () => MakeRequest('HEAD', 'public-with-cors', {}, '', {'format': 'txt'}) + .then(HasStatus200Or204) + .then(HasHeaders({ 'Content-Type': 'text/plain; charset=utf-8' })) + .then(HasNoBody)], + ['HEAD format=json', + () => MakeRequest('HEAD', 'public-with-cors', {}, '', {'format': 'json'}) + .then(HasStatus200Or204) + .then(HasHeaders({ 'Content-Type': 'application/json; charset=utf-8' })) + .then(HasNoBody)], + ['HEAD format=xml', + () => MakeRequest('HEAD', 'public-with-cors', {}, '', {'format': 'xml'}) + .then(HasStatus200Or204) + .then(HasHeaders({ 'Content-Type': 'application/xml; charset=utf-8' })) + .then(HasNoBody)] +]) |