cddl 0.16.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/package.json +5 -1
- package/.release-it.ts +0 -10
- package/docs/README.md +0 -47
- package/docs/arrays.md +0 -356
- package/docs/ast-structure.md +0 -166
- package/docs/basic-types.md +0 -243
- package/docs/cddl-cheatsheet.md +0 -231
- package/docs/comments.md +0 -307
- package/docs/groups.md +0 -351
- package/docs/operators.md +0 -466
- package/docs/properties.md +0 -334
- package/docs/ranges.md +0 -339
- package/docs/references.md +0 -340
- package/docs/variables.md +0 -335
- package/src/ast.ts +0 -180
- package/src/cli/commands/repl.ts +0 -33
- package/src/cli/commands/validate.ts +0 -44
- package/src/cli/constants.ts +0 -1
- package/src/cli/index.ts +0 -18
- package/src/constants.ts +0 -16
- package/src/index.ts +0 -12
- package/src/lexer.ts +0 -238
- package/src/parser.ts +0 -993
- package/src/tokens.ts +0 -50
- package/src/utils.ts +0 -96
- package/tests/__snapshots__/complex_types.test.ts.snap +0 -80
- package/tests/__snapshots__/examples.test.ts.snap +0 -1077
- package/tests/__snapshots__/group-choices.test.ts.snap +0 -403
- package/tests/__snapshots__/parser.test.ts.snap +0 -3045
- package/tests/__snapshots__/webdriver-local.test.ts.snap +0 -11192
- package/tests/__snapshots__/webdriver-remote.test.ts.snap +0 -16350
- package/tests/commands/repl.test.ts +0 -52
- package/tests/commands/validate.test.ts +0 -66
- package/tests/complex_types.test.ts +0 -18
- package/tests/examples.test.ts +0 -25
- package/tests/group-choices.test.ts +0 -132
- package/tests/lexer.test.ts +0 -63
- package/tests/module.test.ts +0 -21
- package/tests/parser.test.ts +0 -63
- package/tests/utils.test.ts +0 -211
- package/tests/webdriver-local.test.ts +0 -15
- package/tests/webdriver-remote.test.ts +0 -15
- package/tsconfig.json +0 -11
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { describe, it, vi, expect } from 'vitest'
|
|
2
|
-
import repl from 'node:repl'
|
|
3
|
-
import { builder, handler, evaluate } from '../../src/cli/commands/repl.js'
|
|
4
|
-
import { Tokens } from '../../src/tokens.js'
|
|
5
|
-
|
|
6
|
-
describe('repl command', () => {
|
|
7
|
-
it('builder', () => {
|
|
8
|
-
const yargs: any = {}
|
|
9
|
-
yargs.epilogue = vi.fn().mockReturnValue(yargs)
|
|
10
|
-
yargs.help = vi.fn().mockReturnValue(yargs)
|
|
11
|
-
builder(yargs)
|
|
12
|
-
|
|
13
|
-
expect(yargs.epilogue).toHaveBeenCalledTimes(1)
|
|
14
|
-
expect(yargs.help).toHaveBeenCalledTimes(1)
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
describe('handler', () => {
|
|
18
|
-
it('starts repl', () => {
|
|
19
|
-
const startSpy = vi.spyOn(repl, 'start').mockReturnValue({} as any)
|
|
20
|
-
handler()
|
|
21
|
-
expect(startSpy).toHaveBeenCalledWith(expect.objectContaining({
|
|
22
|
-
prompt: '> ',
|
|
23
|
-
eval: evaluate
|
|
24
|
-
}))
|
|
25
|
-
startSpy.mockRestore()
|
|
26
|
-
})
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
describe('evaluate', () => {
|
|
30
|
-
it('returns error if no input', () => {
|
|
31
|
-
const cb = vi.fn()
|
|
32
|
-
evaluate('', {}, '', cb)
|
|
33
|
-
expect(cb).toHaveBeenCalledWith(expect.any(Error), null)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
it('tokenizes input using Lexer', () => {
|
|
37
|
-
const cb = vi.fn()
|
|
38
|
-
const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
|
|
39
|
-
|
|
40
|
-
evaluate('foo = 1', {}, '', cb)
|
|
41
|
-
|
|
42
|
-
expect(consoleSpy).toHaveBeenCalledTimes(3) // foo, =, 1
|
|
43
|
-
expect(consoleSpy).toHaveBeenNthCalledWith(1, expect.objectContaining({ Type: Tokens.IDENT, Literal: 'foo' }))
|
|
44
|
-
expect(consoleSpy).toHaveBeenNthCalledWith(2, expect.objectContaining({ Type: Tokens.ASSIGN, Literal: '=' }))
|
|
45
|
-
expect(consoleSpy).toHaveBeenNthCalledWith(3, expect.objectContaining({ Type: Tokens.NUMBER, Literal: '1' }))
|
|
46
|
-
|
|
47
|
-
expect(cb).toHaveBeenCalledWith(null, null)
|
|
48
|
-
|
|
49
|
-
consoleSpy.mockRestore()
|
|
50
|
-
})
|
|
51
|
-
})
|
|
52
|
-
})
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import url from 'node:url'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import { describe, it, vi, expect, beforeEach, afterAll } from 'vitest'
|
|
4
|
-
import { builder, handler } from '../../src/cli/commands/validate.js'
|
|
5
|
-
|
|
6
|
-
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
|
7
|
-
const validCDDL = path.join(__dirname, '..', '..', '..', '..', 'examples', 'webdriver', 'local.cddl')
|
|
8
|
-
const buggyCDDL = path.join(__dirname, '..', '..', '..', '..', 'examples', 'commons', 'buggy.cddl')
|
|
9
|
-
|
|
10
|
-
describe('validate command', () => {
|
|
11
|
-
it('builder', () => {
|
|
12
|
-
const yargs: any = {}
|
|
13
|
-
yargs.epilogue = vi.fn().mockReturnValue(yargs)
|
|
14
|
-
yargs.help = vi.fn().mockReturnValue(yargs)
|
|
15
|
-
builder(yargs)
|
|
16
|
-
|
|
17
|
-
expect(yargs.epilogue).toBeCalledTimes(1)
|
|
18
|
-
expect(yargs.help).toBeCalledTimes(1)
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
describe('handler', () => {
|
|
22
|
-
const consoleLogOrig = console.log.bind(console)
|
|
23
|
-
const consoleErrorOrig = console.error.bind(console)
|
|
24
|
-
const processExitOrig = process.exit.bind(process)
|
|
25
|
-
|
|
26
|
-
beforeEach(() => {
|
|
27
|
-
// @ts-expect-error
|
|
28
|
-
process.exit = vi.fn()
|
|
29
|
-
console.log = vi.fn()
|
|
30
|
-
console.error = vi.fn()
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
afterAll(() => {
|
|
34
|
-
process.exit = processExitOrig
|
|
35
|
-
console.log = consoleLogOrig
|
|
36
|
-
console.error = consoleErrorOrig
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
it('fails if file does not exist', () => {
|
|
40
|
-
handler({ filePath: '/foo/bar', _: [], $0: '' })
|
|
41
|
-
expect(process.exit).toBeCalledTimes(1)
|
|
42
|
-
expect(console.error).toBeCalledTimes(1)
|
|
43
|
-
expect(process.exit).toBeCalledWith(1)
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
it('fails if cddl file is buggy', () => {
|
|
47
|
-
handler({ filePath: buggyCDDL, _: [], $0: '' })
|
|
48
|
-
expect(process.exit).toBeCalledTimes(1)
|
|
49
|
-
expect(console.error).toBeCalledTimes(1)
|
|
50
|
-
expect(process.exit).toBeCalledWith(1)
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
it('passes if cddl file is valid', () => {
|
|
54
|
-
handler({ filePath: validCDDL, _: [], $0: '' })
|
|
55
|
-
expect(process.exit).toBeCalledTimes(0)
|
|
56
|
-
expect(console.log).toBeCalledTimes(1)
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
it('handles relative paths', () => {
|
|
60
|
-
handler({ filePath: 'relative/path/to/file.cddl', _: [], $0: '' })
|
|
61
|
-
expect(process.exit).toBeCalledTimes(1)
|
|
62
|
-
expect(console.error).toBeCalledTimes(1)
|
|
63
|
-
expect(process.exit).toBeCalledWith(1)
|
|
64
|
-
})
|
|
65
|
-
})
|
|
66
|
-
})
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import url from 'node:url'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import { describe, it, expect } from 'vitest'
|
|
4
|
-
|
|
5
|
-
import Parser from '../src/parser.js'
|
|
6
|
-
|
|
7
|
-
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
|
8
|
-
|
|
9
|
-
describe('complex types', () => {
|
|
10
|
-
it('can parse complex types correctly', () => {
|
|
11
|
-
const p = new Parser(path.join(__dirname, '..', '..', '..', 'examples', 'commons', 'complex_types.cddl'))
|
|
12
|
-
const ast = p.parse()
|
|
13
|
-
const localValue = ast.find((item: any) => item.Name === 'LocalValue')
|
|
14
|
-
|
|
15
|
-
expect(localValue).toBeDefined()
|
|
16
|
-
expect(localValue).toMatchSnapshot()
|
|
17
|
-
})
|
|
18
|
-
})
|
package/tests/examples.test.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import url from 'node:url'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import { describe, it, expect } from 'vitest'
|
|
4
|
-
|
|
5
|
-
import Parser from '../src/parser.js'
|
|
6
|
-
|
|
7
|
-
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
|
8
|
-
|
|
9
|
-
describe('examples', () => {
|
|
10
|
-
describe('common', () => {
|
|
11
|
-
const testCases: { name: string, fixture: string }[] = [
|
|
12
|
-
{ name: 'can parse group choice', fixture: 'group_choice.cddl' },
|
|
13
|
-
{ name: 'can parse literals', fixture: 'literals.cddl' },
|
|
14
|
-
{ name: 'can parse mixin union', fixture: 'mixin_union.cddl' },
|
|
15
|
-
{ name: 'can parse named group choice', fixture: 'named_group_choice.cddl' }
|
|
16
|
-
]
|
|
17
|
-
|
|
18
|
-
for (const { name, fixture } of testCases) {
|
|
19
|
-
it(name, async () => {
|
|
20
|
-
const p = new Parser(path.join(__dirname, '..', '..', '..', 'examples', 'commons', fixture))
|
|
21
|
-
expect(p.parse()).toMatchSnapshot()
|
|
22
|
-
})
|
|
23
|
-
}
|
|
24
|
-
})
|
|
25
|
-
})
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
2
|
-
import Parser from '../src/parser.js'
|
|
3
|
-
import * as fs from 'node:fs'
|
|
4
|
-
|
|
5
|
-
vi.mock('node:fs')
|
|
6
|
-
|
|
7
|
-
describe('Group Choice Parsing', () => {
|
|
8
|
-
const parse = (cddl: string) => {
|
|
9
|
-
vi.mocked(fs.readFileSync).mockReturnValue(cddl)
|
|
10
|
-
const parser = new Parser('dummy.cddl')
|
|
11
|
-
return parser.parse()
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
vi.clearAllMocks()
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
describe('Group Choice (//)', () => {
|
|
19
|
-
it('should verify group choice operator //', () => {
|
|
20
|
-
const cddl = `
|
|
21
|
-
mygroup = (int // text)
|
|
22
|
-
`
|
|
23
|
-
const ast = parse(cddl)
|
|
24
|
-
expect(ast).toMatchSnapshot()
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
it('should throw error when group choice operator // is at start of group', () => {
|
|
28
|
-
const cddl = `
|
|
29
|
-
mygroup = (// int)
|
|
30
|
-
`
|
|
31
|
-
expect(() => parse(cddl)).toThrowError('Unexpected group choice operator "//" at start of group')
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
it('should parse nested group choice', () => {
|
|
35
|
-
const cddl = `
|
|
36
|
-
mygroup = ((int // text))
|
|
37
|
-
`
|
|
38
|
-
const ast = parse(cddl)
|
|
39
|
-
expect(ast).toMatchSnapshot()
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
it('should parse group choice with multiple items', () => {
|
|
43
|
-
const cddl = `
|
|
44
|
-
mygroup = (int, text // float)
|
|
45
|
-
`
|
|
46
|
-
const ast = parse(cddl)
|
|
47
|
-
expect(ast).toMatchSnapshot()
|
|
48
|
-
})
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
describe('Map Group Choice', () => {
|
|
52
|
-
it('should parse group choice inside map', () => {
|
|
53
|
-
const cddl = `
|
|
54
|
-
mymap = {
|
|
55
|
-
"a" => 1 //
|
|
56
|
-
"b" => 2
|
|
57
|
-
}
|
|
58
|
-
`
|
|
59
|
-
const ast = parse(cddl)
|
|
60
|
-
expect(ast).toMatchSnapshot()
|
|
61
|
-
})
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
describe('Type Choice (/)', () => {
|
|
65
|
-
it('should parse type choice inside group', () => {
|
|
66
|
-
const cddl = `
|
|
67
|
-
mygroup = (int / text)
|
|
68
|
-
`
|
|
69
|
-
const ast = parse(cddl)
|
|
70
|
-
expect(ast).toMatchSnapshot()
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
it('should treat comments around type choice separators the same', () => {
|
|
74
|
-
const slashAfterComment = `
|
|
75
|
-
FlowStrategy = "drop-oldest" ; Discard oldest when buffer is full
|
|
76
|
-
/ "pause-producer" ; Apply backpressure to slow production
|
|
77
|
-
/ "sample" ; Deliver every Nth event under pressure
|
|
78
|
-
`
|
|
79
|
-
const slashBeforeComment = `
|
|
80
|
-
FlowStrategy = "drop-oldest" / ; Discard oldest when buffer is full
|
|
81
|
-
"pause-producer" / ; Apply backpressure to slow production
|
|
82
|
-
"sample" ; Deliver every Nth event under pressure
|
|
83
|
-
`
|
|
84
|
-
|
|
85
|
-
expect(parse(slashAfterComment)).toEqual(parse(slashBeforeComment))
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
// This tests the change: closingTokens.includes(Tokens.RPAREN) && this.peekToken.Type === Tokens.SLASH
|
|
89
|
-
it('should correctly handle slash in mixed context', () => {
|
|
90
|
-
const cddl = `
|
|
91
|
-
myrule = [ (int / text) ]
|
|
92
|
-
`
|
|
93
|
-
const ast = parse(cddl)
|
|
94
|
-
expect(ast).toMatchSnapshot()
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
it('should parse inline array alternatives inside map properties', () => {
|
|
98
|
-
const cddl = `
|
|
99
|
-
StorePutParams = {
|
|
100
|
-
storeNamespace: [* text],
|
|
101
|
-
key: text,
|
|
102
|
-
value: {* text => any},
|
|
103
|
-
? index: bool / [* text],
|
|
104
|
-
? ttl: uint,
|
|
105
|
-
}
|
|
106
|
-
`
|
|
107
|
-
const ast = parse(cddl)
|
|
108
|
-
expect(ast).toMatchSnapshot()
|
|
109
|
-
})
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
describe('Blocks with Braces', () => {
|
|
113
|
-
// Covers changes in openSegment and parseAssignmentValue regarding Tokens.LBRACE
|
|
114
|
-
it('should parse nested group inside map', () => {
|
|
115
|
-
// This relates to the removal of special LPAREN handling inside LBRACE in openSegment
|
|
116
|
-
const cddl = `
|
|
117
|
-
myrule = { (int) }
|
|
118
|
-
`
|
|
119
|
-
const ast = parse(cddl)
|
|
120
|
-
// Expecting parsing to succeed and structure to be correct
|
|
121
|
-
expect(ast).toMatchSnapshot()
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
it('should parse bare group inside brace', () => {
|
|
125
|
-
const cddl = `
|
|
126
|
-
myrule = { int }
|
|
127
|
-
`
|
|
128
|
-
const ast = parse(cddl)
|
|
129
|
-
expect(ast).toMatchSnapshot()
|
|
130
|
-
})
|
|
131
|
-
})
|
|
132
|
-
})
|
package/tests/lexer.test.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest'
|
|
2
|
-
|
|
3
|
-
import { Tokens } from '../src/tokens.js'
|
|
4
|
-
import Lexer from '../src/lexer.js'
|
|
5
|
-
|
|
6
|
-
describe('lexer', () => {
|
|
7
|
-
it('should allow to read token', () => {
|
|
8
|
-
const input = '=+(){},/<>'
|
|
9
|
-
const tests = [
|
|
10
|
-
[Tokens.ASSIGN, '='],
|
|
11
|
-
[Tokens.PLUS, '+'],
|
|
12
|
-
[Tokens.LPAREN, '('],
|
|
13
|
-
[Tokens.RPAREN, ')'],
|
|
14
|
-
[Tokens.LBRACE, '{'],
|
|
15
|
-
[Tokens.RBRACE, '}'],
|
|
16
|
-
[Tokens.COMMA, ','],
|
|
17
|
-
[Tokens.SLASH, '/'],
|
|
18
|
-
[Tokens.LT, '<'],
|
|
19
|
-
[Tokens.GT, '>']
|
|
20
|
-
]
|
|
21
|
-
|
|
22
|
-
const l = new Lexer(input)
|
|
23
|
-
for (const [Type, Literal] of tests) {
|
|
24
|
-
const token = l.nextToken()
|
|
25
|
-
expect(token.Type).toBe(Type)
|
|
26
|
-
expect(token.Literal).toBe(Literal)
|
|
27
|
-
}
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('should read identifiers and comments', () => {
|
|
31
|
-
const input = ' headers, ; Headers for the recipient'
|
|
32
|
-
const tests = [
|
|
33
|
-
[Tokens.IDENT, 'headers'],
|
|
34
|
-
[Tokens.COMMA, ','],
|
|
35
|
-
[Tokens.COMMENT, '; Headers for the recipient']
|
|
36
|
-
]
|
|
37
|
-
|
|
38
|
-
const l = new Lexer(input)
|
|
39
|
-
for (const [Type, Literal] of tests) {
|
|
40
|
-
const token = l.nextToken()
|
|
41
|
-
expect(token.Type).toBe(Type)
|
|
42
|
-
expect(token.Literal).toBe(Literal)
|
|
43
|
-
}
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
it('should correctly report location info', () => {
|
|
47
|
-
const input = 'a = 1'
|
|
48
|
-
const l = new Lexer(input)
|
|
49
|
-
|
|
50
|
-
// consume tokens until EOF
|
|
51
|
-
while (l.nextToken().Type !== 'EOF') {}
|
|
52
|
-
|
|
53
|
-
// consume more EOFs to push position further
|
|
54
|
-
for (let i = 0; i < 10; ++i) {
|
|
55
|
-
l.nextToken()
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// This should trigger the fallback
|
|
59
|
-
const locEnd = l.getLocation()
|
|
60
|
-
expect(locEnd.line).toBe(0)
|
|
61
|
-
expect(locEnd.position).toBe(0)
|
|
62
|
-
})
|
|
63
|
-
})
|
package/tests/module.test.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import url from 'node:url'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import { describe, it, expect } from 'vitest'
|
|
4
|
-
|
|
5
|
-
import CDDL from '../src/index.js'
|
|
6
|
-
|
|
7
|
-
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
|
8
|
-
const validCDDL = path.join(__dirname, '..', '..', '..', 'examples', 'commons', 'arrays.cddl')
|
|
9
|
-
const buggyCDDL = path.join(__dirname, '..', '..', '..', 'examples', 'commons', 'buggy.cddl')
|
|
10
|
-
|
|
11
|
-
describe('validate', () => {
|
|
12
|
-
it('should return a json in success case', () => {
|
|
13
|
-
const ast = CDDL.parse(validCDDL)
|
|
14
|
-
expect(typeof ast).toBe('object')
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
it('should throw an error if invalud', () => {
|
|
18
|
-
expect(() => CDDL.parse(buggyCDDL))
|
|
19
|
-
.toThrow()
|
|
20
|
-
})
|
|
21
|
-
})
|
package/tests/parser.test.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import url from 'node:url'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import fs from 'node:fs'
|
|
4
|
-
import { describe, it, expect, vi } from 'vitest'
|
|
5
|
-
|
|
6
|
-
import Parser from '../src/parser.js'
|
|
7
|
-
|
|
8
|
-
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
|
9
|
-
|
|
10
|
-
describe('parser', () => {
|
|
11
|
-
const testCases: { name: string, fixture: string }[] = [
|
|
12
|
-
{ name: 'should correctly parse CDDL file', fixture: 'example.cddl' },
|
|
13
|
-
{ name: 'can parse compositions', fixture: 'compositions.cddl' },
|
|
14
|
-
{ name: 'can parse ranges', fixture: 'ranges.cddl' },
|
|
15
|
-
{ name: 'can parse occurrences', fixture: 'occurrences.cddl' },
|
|
16
|
-
{ name: 'can parse arrays', fixture: 'arrays.cddl' },
|
|
17
|
-
{ name: 'can parse unwrapped arrays', fixture: 'unwrapping.cddl' },
|
|
18
|
-
{ name: 'can parse comments', fixture: 'comments.cddl' },
|
|
19
|
-
{ name: 'can parse choices', fixture: 'choices.cddl' },
|
|
20
|
-
{ name: 'can parse nested groups', fixture: 'nested.cddl' },
|
|
21
|
-
{ name: 'can parse operators', fixture: 'operators.cddl' }
|
|
22
|
-
]
|
|
23
|
-
|
|
24
|
-
for (const { name, fixture } of testCases) {
|
|
25
|
-
it(name, async () => {
|
|
26
|
-
const p = new Parser(path.join(__dirname, '..', '..', '..', 'examples', 'commons', fixture))
|
|
27
|
-
expect(p.parse()).toMatchSnapshot()
|
|
28
|
-
})
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
it('throws if group identifier is missing', () => {
|
|
32
|
-
vi.spyOn(fs, 'readFileSync').mockReturnValue('=')
|
|
33
|
-
const p = new Parser('foo.cddl')
|
|
34
|
-
expect(() => p.parse()).toThrow('group identifier expected')
|
|
35
|
-
vi.restoreAllMocks()
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('throws if assignment operator is missing', () => {
|
|
39
|
-
vi.spyOn(fs, 'readFileSync').mockReturnValue('groupName bar')
|
|
40
|
-
const p = new Parser('foo.cddl')
|
|
41
|
-
expect(() => p.parse()).toThrow('group identifier expected')
|
|
42
|
-
vi.restoreAllMocks()
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
it('skips blank comment lines in assignment comments', () => {
|
|
46
|
-
vi.spyOn(fs, 'readFileSync').mockReturnValue('; heading\n;\nfoo = int\n')
|
|
47
|
-
const p = new Parser('foo.cddl')
|
|
48
|
-
|
|
49
|
-
expect(p.parse()).toEqual([{
|
|
50
|
-
Type: 'variable',
|
|
51
|
-
Name: 'foo',
|
|
52
|
-
IsChoiceAddition: false,
|
|
53
|
-
PropertyType: ['int'],
|
|
54
|
-
Comments: [{
|
|
55
|
-
Type: 'comment',
|
|
56
|
-
Content: 'heading',
|
|
57
|
-
Leading: false
|
|
58
|
-
}]
|
|
59
|
-
}])
|
|
60
|
-
|
|
61
|
-
vi.restoreAllMocks()
|
|
62
|
-
})
|
|
63
|
-
})
|
package/tests/utils.test.ts
DELETED
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest'
|
|
2
|
-
|
|
3
|
-
import type {
|
|
4
|
-
Array as CDDLArray,
|
|
5
|
-
Assignment,
|
|
6
|
-
Comment,
|
|
7
|
-
Group,
|
|
8
|
-
NativeTypeWithOperator,
|
|
9
|
-
Property,
|
|
10
|
-
PropertyReference,
|
|
11
|
-
Variable
|
|
12
|
-
} from '../src/ast.js'
|
|
13
|
-
import { Tokens, type Token } from '../src/tokens.js'
|
|
14
|
-
import {
|
|
15
|
-
hasSpecialNumberCharacter,
|
|
16
|
-
isAlphabeticCharacter,
|
|
17
|
-
isCDDLArray,
|
|
18
|
-
isDigit,
|
|
19
|
-
isGroup,
|
|
20
|
-
isLetter,
|
|
21
|
-
isLiteralWithValue,
|
|
22
|
-
isNamedGroupReference,
|
|
23
|
-
isNativeTypeWithOperator,
|
|
24
|
-
isProperty,
|
|
25
|
-
isPropertyReference,
|
|
26
|
-
isRange,
|
|
27
|
-
isUnNamedProperty,
|
|
28
|
-
isVariable,
|
|
29
|
-
parseNumberValue,
|
|
30
|
-
pascalCase
|
|
31
|
-
} from '../src/utils.js'
|
|
32
|
-
|
|
33
|
-
const comments: Comment[] = []
|
|
34
|
-
|
|
35
|
-
function createVariable (): Variable {
|
|
36
|
-
return {
|
|
37
|
-
Type: 'variable',
|
|
38
|
-
Name: 'my-variable',
|
|
39
|
-
IsChoiceAddition: false,
|
|
40
|
-
PropertyType: 'tstr',
|
|
41
|
-
Comments: comments
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function createGroup (): Group {
|
|
46
|
-
return {
|
|
47
|
-
Type: 'group',
|
|
48
|
-
Name: 'my-group',
|
|
49
|
-
IsChoiceAddition: false,
|
|
50
|
-
Properties: [],
|
|
51
|
-
Comments: comments
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function createArray (): CDDLArray {
|
|
56
|
-
return {
|
|
57
|
-
Type: 'array',
|
|
58
|
-
Name: 'my-array',
|
|
59
|
-
Values: [],
|
|
60
|
-
Comments: comments
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function createProperty (overrides: Partial<Property> = {}): Property {
|
|
65
|
-
return {
|
|
66
|
-
HasCut: false,
|
|
67
|
-
Occurrence: { n: 1, m: 1 },
|
|
68
|
-
Name: 'foo',
|
|
69
|
-
Type: 'tstr',
|
|
70
|
-
Comments: comments,
|
|
71
|
-
...overrides
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
describe('utils', () => {
|
|
76
|
-
describe('character helpers', () => {
|
|
77
|
-
it('should detect letters and alphabetic characters', () => {
|
|
78
|
-
expect(isLetter('a')).toBe(true)
|
|
79
|
-
expect(isLetter('Z')).toBe(true)
|
|
80
|
-
expect(isLetter('1')).toBe(false)
|
|
81
|
-
|
|
82
|
-
expect(isAlphabeticCharacter('a')).toBe(true)
|
|
83
|
-
expect(isAlphabeticCharacter(Tokens.ATSIGN)).toBe(true)
|
|
84
|
-
expect(isAlphabeticCharacter(Tokens.UNDERSCORE)).toBe(true)
|
|
85
|
-
expect(isAlphabeticCharacter(Tokens.DOLLAR)).toBe(true)
|
|
86
|
-
expect(isAlphabeticCharacter('-')).toBe(false)
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
it('should detect digits and special number characters', () => {
|
|
90
|
-
expect(isDigit('1')).toBe(true)
|
|
91
|
-
expect(isDigit('0')).toBe(true)
|
|
92
|
-
expect(isDigit('a')).toBe(false)
|
|
93
|
-
expect(isDigit(Tokens.NL)).toBe(false)
|
|
94
|
-
expect(isDigit(Tokens.SPACE)).toBe(false)
|
|
95
|
-
|
|
96
|
-
expect(hasSpecialNumberCharacter(Tokens.MINUS.charCodeAt(0))).toBe(true)
|
|
97
|
-
expect(hasSpecialNumberCharacter(Tokens.DOT.charCodeAt(0))).toBe(true)
|
|
98
|
-
expect(hasSpecialNumberCharacter('x'.charCodeAt(0))).toBe(true)
|
|
99
|
-
expect(hasSpecialNumberCharacter('b'.charCodeAt(0))).toBe(true)
|
|
100
|
-
expect(hasSpecialNumberCharacter('1'.charCodeAt(0))).toBe(false)
|
|
101
|
-
})
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
describe('number parsing helpers', () => {
|
|
105
|
-
it('should parse floats, integers and prefixed numbers', () => {
|
|
106
|
-
const floatToken: Token = { Type: Tokens.FLOAT, Literal: '12.5' }
|
|
107
|
-
const intToken: Token = { Type: Tokens.INT, Literal: '42' }
|
|
108
|
-
const hexToken: Token = { Type: Tokens.INT, Literal: '0x10' }
|
|
109
|
-
const binaryToken: Token = { Type: Tokens.INT, Literal: '0b10' }
|
|
110
|
-
|
|
111
|
-
expect(parseNumberValue(floatToken)).toBe(12.5)
|
|
112
|
-
expect(parseNumberValue(intToken)).toBe(42)
|
|
113
|
-
expect(parseNumberValue(hexToken)).toBe('0x10')
|
|
114
|
-
expect(parseNumberValue(binaryToken)).toBe('0b10')
|
|
115
|
-
})
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
describe('name helpers', () => {
|
|
119
|
-
it('should convert names to pascal case', () => {
|
|
120
|
-
expect(pascalCase('my-example_name')).toBe('MyExampleName')
|
|
121
|
-
})
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
describe('assignment guards', () => {
|
|
125
|
-
it('should detect variables, groups and arrays', () => {
|
|
126
|
-
const variable: Assignment = createVariable()
|
|
127
|
-
const group: Assignment = createGroup()
|
|
128
|
-
const array: Assignment = createArray()
|
|
129
|
-
|
|
130
|
-
expect(isVariable(variable)).toBe(true)
|
|
131
|
-
expect(isVariable(group)).toBe(false)
|
|
132
|
-
|
|
133
|
-
expect(isGroup(group)).toBe(true)
|
|
134
|
-
expect(isGroup(variable)).toBe(false)
|
|
135
|
-
|
|
136
|
-
expect(isCDDLArray(array)).toBe(true)
|
|
137
|
-
expect(isCDDLArray(group)).toBe(false)
|
|
138
|
-
})
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
describe('property guards', () => {
|
|
142
|
-
it('should detect named and unnamed properties', () => {
|
|
143
|
-
const property = createProperty()
|
|
144
|
-
const unnamedProperty = createProperty({ Name: '' })
|
|
145
|
-
|
|
146
|
-
expect(isProperty(property)).toBe(true)
|
|
147
|
-
expect(isProperty({ Name: 'foo' })).toBe(false)
|
|
148
|
-
|
|
149
|
-
expect(isUnNamedProperty(unnamedProperty)).toBe(true)
|
|
150
|
-
expect(isUnNamedProperty(property)).toBe(false)
|
|
151
|
-
})
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
describe('reference and operator guards', () => {
|
|
155
|
-
it('should detect property references and named group references', () => {
|
|
156
|
-
const groupReference: PropertyReference = {
|
|
157
|
-
Type: 'group',
|
|
158
|
-
Value: 'my-group',
|
|
159
|
-
Unwrapped: false
|
|
160
|
-
}
|
|
161
|
-
const numericGroupReference: PropertyReference = {
|
|
162
|
-
Type: 'group',
|
|
163
|
-
Value: 123,
|
|
164
|
-
Unwrapped: false
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
expect(isPropertyReference(groupReference)).toBe(true)
|
|
168
|
-
expect(isPropertyReference({ Type: 'group' })).toBe(false)
|
|
169
|
-
|
|
170
|
-
expect(isNamedGroupReference(groupReference)).toBe(true)
|
|
171
|
-
expect(isNamedGroupReference(numericGroupReference)).toBe(false)
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
it('should detect native types with operators and ranges', () => {
|
|
175
|
-
const nativeTypeWithOperator: NativeTypeWithOperator = {
|
|
176
|
-
Type: {
|
|
177
|
-
Type: 'group',
|
|
178
|
-
Value: 'my-group',
|
|
179
|
-
Unwrapped: false
|
|
180
|
-
},
|
|
181
|
-
Operator: {
|
|
182
|
-
Type: 'default',
|
|
183
|
-
Value: 'tstr'
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
const rangeReference: PropertyReference = {
|
|
187
|
-
Type: 'range',
|
|
188
|
-
Value: {
|
|
189
|
-
Min: 0,
|
|
190
|
-
Max: 10,
|
|
191
|
-
Inclusive: true
|
|
192
|
-
},
|
|
193
|
-
Unwrapped: false
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
expect(isNativeTypeWithOperator(nativeTypeWithOperator)).toBe(true)
|
|
197
|
-
expect(isNativeTypeWithOperator({ Type: 'tstr' })).toBe(false)
|
|
198
|
-
|
|
199
|
-
expect(isRange({ Type: rangeReference })).toBe(true)
|
|
200
|
-
expect(isRange({ Type: 'range' })).toBe(false)
|
|
201
|
-
})
|
|
202
|
-
})
|
|
203
|
-
|
|
204
|
-
describe('literal guards', () => {
|
|
205
|
-
it('should detect literals with values', () => {
|
|
206
|
-
expect(isLiteralWithValue({ Type: 'literal', Value: 'foo' })).toBe(true)
|
|
207
|
-
expect(isLiteralWithValue({ Type: 'literal' })).toBe(false)
|
|
208
|
-
expect(isLiteralWithValue({ Type: 'group', Value: 'foo' })).toBe(false)
|
|
209
|
-
})
|
|
210
|
-
})
|
|
211
|
-
})
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import url from 'node:url'
|
|
2
|
-
import path from 'node:path'
|
|
3
|
-
import { describe, it, expect } from 'vitest'
|
|
4
|
-
|
|
5
|
-
import Parser from '../src/parser.js'
|
|
6
|
-
|
|
7
|
-
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
|
8
|
-
|
|
9
|
-
describe('webdriver local cddl', () => {
|
|
10
|
-
it('can parse local.cddl', () => {
|
|
11
|
-
const filePath = path.join(__dirname, '..', '..', '..', 'examples', 'webdriver', 'local.cddl')
|
|
12
|
-
const p = new Parser(filePath)
|
|
13
|
-
expect(p.parse()).toMatchSnapshot()
|
|
14
|
-
})
|
|
15
|
-
})
|