summaryrefslogtreecommitdiff
path: root/test/cors/test-container.js
diff options
context:
space:
mode:
authorTim Burke <tim.burke@gmail.com>2018-01-11 16:24:24 -0800
committerTim Burke <tim.burke@gmail.com>2021-03-01 10:09:03 -0800
commitc5152ed4d3a37c5e0017be9f0445bf0868561b96 (patch)
tree0e7dc25d05978bc88ba99659868861d155693c73 /test/cors/test-container.js
parent5c3eb488f2df5a93a9899a406fc9a4658efb272b (diff)
downloadswift-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.js148
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)]
+])