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

(WIP) Add tck tests #1

Merged
merged 26 commits into from
Mar 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
360891c
Add tck tests for "Format" and "File Structure" spec sections
postatum Jan 9, 2020
9ebba32
Add more tck tests
postatum Jan 10, 2020
4f46369
Add more tck tests
postatum Jan 10, 2020
51a7b04
Add more tck tests
postatum Jan 13, 2020
7869058
Add more tck tests
postatum Jan 13, 2020
a8de062
Add more tck tests
postatum Jan 13, 2020
1ed14c7
Add more tck tests. Extend existing ones.
postatum Jan 15, 2020
652103f
Add Components Object tests. Rename few tests.
postatum Jan 15, 2020
39464d7
Add Reference Object tck tests
postatum Jan 15, 2020
083a68a
Add tck tests for Schema Object
postatum Jan 16, 2020
46de081
Add more tck tests
postatum Jan 16, 2020
55eba1e
Add tests for fields types
postatum Jan 16, 2020
d398092
Finish adding tests for fields types
postatum Jan 17, 2020
ef2323f
Implement manifest gen. Generate manifest
postatum Jan 17, 2020
cf85aa9
Port initial version of tck runner
postatum Jan 17, 2020
f6cb689
Use .yml extension for reffered files
postatum Jan 17, 2020
81d46c2
Fix tck file issue
postatum Jan 17, 2020
fb68e07
Add/fix js runners code
postatum Jan 17, 2020
a64dcbd
Add development note
postatum Jan 17, 2020
601fa9d
Add gen-manifest note to contrib
postatum Jan 17, 2020
67d941c
Add more tests to address initial notes
postatum Jan 27, 2020
03653bd
Add gh actions workflow to publish to gh-pages
postatum Jan 28, 2020
3e92f60
Rework GH Actions workflow to use SSH
postatum Jan 29, 2020
f0e1b4f
Address initial PR review notes
postatum Mar 4, 2020
e0d6776
Reduce some tests size
postatum Mar 4, 2020
969b0aa
Delete invalid test
postatum Mar 19, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
28 changes: 28 additions & 0 deletions .github/workflows/publish-gh-pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Publish Github Pages

on:
push:
branches:
- add_tck_tests

jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Build tck runner reports
run: make
working-directory: ./runner
- name: Create .nojekyll file
run: touch runner/reports/html/.nojekyll
- name: Install SSH Client
uses: webfactory/[email protected]
with:
ssh-private-key: ${{ secrets.DEPLOY_KEY }}
- name: Deploy to Github Pages
uses: JamesIves/github-pages-deploy-action@releases/v3
with:
SSH: true
BRANCH: gh-pages # The branch the action should deploy to.
FOLDER: runner/reports/html/ # The folder the action should deploy.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
18 changes: 18 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Contributing

Each test case should contain the following files:
* A valid `*valid*.yaml` file showcasing valid use of the feature under test
* An invalid `*invalid*.yaml` files showcasing invalid use of the feature under test

Please place new tests in one of `tests/asyncapi-2.0` sub-folders. Name of the target folder should correspond to the name of the feature your tests test. E.g. if your new `.yaml` tests `Info Object`, place it in `tests/asyncapi-2.0/Info Object`.

Non-AsyncAPI files (libraries, extensions, etc.) must have a `.yml` extension instead of `.yaml`.

After adding/moving/deleting tck files, manifest has to be regenerated with:
```sh
npm run gen-manifest
```

## Running tests

We've created a separate project called [tck runner](./runner) to run all the tests contained in the AsyncAPI TCK. By following the instructions on that directory, you should be able to test any new test case that you may want to contribute against the different projects that this runner covers.
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,18 @@
# tck
# AsyncAPI tck

AsyncAPI's Test Compatibility Kit (AsyncAPI TCK) provides a way for any AsyncAPI processor to test its compliance with the AsyncAPI 2.0 Spec. AsyncAPI TCK contains a set of AsyncAPI documents meant to be used to test correct and incorrect usage of each AsyncAPI feature.

## Naming convention

- `*valid*.yaml`: valid AsyncAPI file expected to be successfully processed
- `*invalid*.yaml`: invalid AsyncAPI file with syntax/semantic/spec error(s), expected to be unsuccessfully processed (error or exit code returned)

Note that this repository contains a [manifest file](./manifest.json) that lists all tests in the order their respective tested features appear in the AsyncAPI 2.0 Specification.

Names of folders' tests reside in correspond to AsyncAPI 2.0 Specification sections names.

Non-AsyncAPI files (libraries, extensions, etc.) must have a `.yml` extension instead of `.yaml`.

## Contributing

We welcome contributions! If you have a new test case in mind, feel free to submit a pull request. More info on how to do that [here](./CONTRIBUTING.md).
155 changes: 155 additions & 0 deletions genmanifest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
const path = require('path')
const fs = require('fs')
const walk = require('walk')

// Features listed in order they appear in the spec spec.
const FEATURES_PRIORITY = [
'Format',
'File Structure',
'AsyncAPI Object',
'AsyncAPI Version String',
'Identifier',
'Info Object',
'Contact Object',
'License Object',
'Servers Object',
'Server Object',
'Server Variable Object',
'Channels Object',
'Channel Item Object',
'Operation Object',
'Operation Trait Object',
'Message Object',
'Message Trait Object',
'Tags Object',
'Tag Object',
'External Documentation Object',
'Components Object',
'Reference Object',
'Schema Object',
'Security Scheme Object',
'Security Requirement Object',
'Parameters Object',
'Parameter Object',
'Server Bindings Object',
'Channel Bindings Object',
'Operation Bindings Object',
'Message Bindings Object',
'Correlation ID Object',
'Specification Extensions'
]

const EXT = '.yaml'

function main () {
const projRoot = path.resolve(__dirname)
const inputRoot = getInputDirPath()
let filesPaths = listFiles(inputRoot)
filesPaths = sortFilesPaths(inputRoot, filesPaths)
filesPaths = makePathsRelative(projRoot, filesPaths)
generateManifest(projRoot, filesPaths)
}

// Gets absolute path of input folder
function getInputDirPath () {
let dirPath = process.argv[2]

if (!fs.existsSync(dirPath)) {
console.error(`'${dirPath}' not found`)
return
}

dirPath = path.resolve(dirPath)
if (!fs.lstatSync(dirPath).isDirectory()) {
console.error(`'${dirPath}' is not a directory`)
return
}
return dirPath
}

// Lists files with a particular extension under directory path
function listFiles (dirPath) {
let files = []
const options = {
listeners: {
file: (root, fileStats, next) => {
if (fileStats.name.indexOf(EXT) >= 0) {
files.push(path.join(root, fileStats.name))
}
next()
}
}
}
walk.walkSync(dirPath, options)
return files
}

// Sorts string filesPaths according to features definition order in a spec
function sortFilesPaths (filesRoot, filesPaths) {
const pathObjs = extendWithPriority(
filesRoot, filesPaths, FEATURES_PRIORITY.slice())
const sortedPathObjs = pathObjs.sort((obj1, obj2) => {
return obj1.priority - obj2.priority
})
return sortedPathObjs.map((obj) => {
return obj.path
})
}

// Makes fiels paths relative to a directory
function makePathsRelative (dirPath, filesPaths) {
return filesPaths.map((pth) => {
return path.relative(dirPath, pth)
})
}

// Turns plain file paths into objects of type {priority: INT, path: STRING}
// E.g.:
// > let featuresPriority = ['methodresponses', 'overlays']
// > extendWithPriority('/foo/bar', '/foo/bar/Overlays/some/file.ext')
// > {priority: 2, path: '/foo/bar/Overlays/some/file.ext'}
// > extendWithPriority('/foo/bar', '/foo/bar/qweqwe/some/file.ext')
// > {priority: 3, path: '/foo/bar/qweqwe/some/file.ext'}
//
// Override this to change logic of picking priority.
function extendWithPriority (filesRoot, filesPaths, featuresPriority) {
featuresPriority = featuresPriority.map(x => x.toLowerCase())
return filesPaths.map((pth) => {
const piece = getFirstPathPiece(filesRoot, pth).toLowerCase()
let priority = featuresPriority.findIndex(el => el === piece)

// Feature name not found. Adding it to the list allows sorting not
// found features.
if (priority === -1) {
featuresPriority.push(piece)
priority = featuresPriority.length - 1
}
priority += 1 // Make 1-based
return {path: pth, priority: priority}
})
}

// Gets relative folder 'root' name of files file path.
// E.g.:
// > const filesRoot = '/foo/bar'
// > const fielPath = '/foo/bar/MethodResponses/some/file.ext'
// > getFirstPathPiece(filesRoot, fielPath)
// > 'methodresponses'
function getFirstPathPiece (filesRoot, fielPath) {
const relPath = path.relative(filesRoot, fielPath)
return relPath.split(path.sep)[0].toLowerCase()
}

// Generates and writes manifest file
function generateManifest (dirPath, filesPaths) {
const data = {
description: 'Files listed in order corresponding AsyncAPI ' +
'feature appears in AsyncAPI 2.0 Specification',
filePaths: filesPaths
}
const manifestPath = path.join(dirPath, 'manifest.json')
console.log(`Writing manifest file to ${manifestPath}`)
fs.writeFileSync(manifestPath, JSON.stringify(data, null, 4))
}

main()
Loading