| 9 | } |
| 10 | |
| 11 | async function runTest( |
| 12 | dbadapter: dbadapters.IDbAdapter, |
| 13 | testCase: dataform.ITest |
| 14 | ): Promise<dataform.ITestResult> { |
| 15 | // TODO: Test results are currently limited to 1MB. |
| 16 | // We should paginate test results to remove this limit. |
| 17 | let actualResults; |
| 18 | let expectedResults; |
| 19 | try { |
| 20 | [actualResults, expectedResults] = await Promise.all([ |
| 21 | dbadapter.execute(testCase.testQuery, { byteLimit: 1024 * 1024 }), |
| 22 | dbadapter.execute(testCase.expectedOutputQuery, { byteLimit: 1024 * 1024 }) |
| 23 | ]); |
| 24 | } catch (e) { |
| 25 | return { |
| 26 | name: testCase.name, |
| 27 | successful: false, |
| 28 | messages: [`Error thrown: ${e.message}.`] |
| 29 | }; |
| 30 | } |
| 31 | |
| 32 | // Check row counts. |
| 33 | if (actualResults.rows.length !== expectedResults.rows.length) { |
| 34 | return { |
| 35 | name: testCase.name, |
| 36 | successful: false, |
| 37 | messages: [ |
| 38 | `Expected ${expectedResults.rows.length} rows, but saw ${actualResults.rows.length} rows.` |
| 39 | ] |
| 40 | }; |
| 41 | } |
| 42 | // If the result set is empty and the number of actual rows is equal to the number of expected rows |
| 43 | // (asserted above), this test is therefore successful. |
| 44 | if (actualResults.rows.length === 0) { |
| 45 | return { |
| 46 | name: testCase.name, |
| 47 | successful: true |
| 48 | }; |
| 49 | } |
| 50 | |
| 51 | // Check column sets. |
| 52 | const actualColumns = Object.keys(actualResults.rows[0]); |
| 53 | const expectedColumns = Object.keys(expectedResults.rows[0]); |
| 54 | if (actualColumns.length !== expectedColumns.length) { |
| 55 | return { |
| 56 | name: testCase.name, |
| 57 | successful: false, |
| 58 | messages: [`Expected columns "${expectedColumns}", but saw "${actualColumns}".`] |
| 59 | }; |
| 60 | } |
| 61 | // We assume: (a) column order does not matter, and (b) column names are unique. |
| 62 | for (const expectedColumn of expectedColumns) { |
| 63 | if ( |
| 64 | !actualColumns.some( |
| 65 | actualColumn => normalizeColumnName(actualColumn) === normalizeColumnName(expectedColumn) |
| 66 | ) |
| 67 | ) { |
| 68 | return { |