-
-
Notifications
You must be signed in to change notification settings - Fork 902
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
149 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -68,6 +68,7 @@ For timestamp UUIDs, namespace UUIDs, and other options read on ... | |
| [`uuid.v6()`](#uuidv6options-buffer-offset) | Create a version 6 (timestamp, reordered) UUID | New in `uuid@10` | | ||
| [`uuid.v6ToV1()`](#uuidv6tov1uuid) | Create a version 1 UUID from a version 6 UUID | New in `uuid@10` | | ||
| [`uuid.v7()`](#uuidv7options-buffer-offset) | Create a version 7 (Unix Epoch time-based) UUID | New in `uuid@10` | | ||
| ~~[`uuid.v8()`](#uuidv8)~~ | "Intentionally left blank" | | | ||
| [`uuid.validate()`](#uuidvalidatestr) | Test a string to see if it is a valid UUID | New in `[email protected]` | | ||
| [`uuid.version()`](#uuidversionstr) | Detect RFC version of a UUID | New in `[email protected]` | | ||
|
||
|
@@ -120,7 +121,7 @@ import { parse as uuidParse } from 'uuid'; | |
const bytes = uuidParse('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); | ||
|
||
// Convert to hex strings to show byte order (for documentation purposes) | ||
[...bytes].map((v) => v.toString(16).padStart(2, '0')); // ⇨ | ||
[...bytes].map((v) => v.toString(16).padStart(2, '0')); // ⇨ | ||
// [ | ||
// '6e', 'c0', 'bd', '7f', | ||
// '11', 'c0', '43', 'da', | ||
|
@@ -353,6 +354,14 @@ import { v7 as uuidv7 } from 'uuid'; | |
uuidv7(); // ⇨ '01695553-c90c-722d-9b5d-b38dfbbd4bed' | ||
``` | ||
|
||
### ~~uuid.v8()~~ | ||
|
||
**_"Intentionally left blank"_** | ||
|
||
<!-- prettier-ignore --> | ||
> [!NOTE] | ||
> Version 8 (experimental) UUIDs are "[for experimental or vendor-specific use cases](https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-8)". The RFC does not define a creation algorithm for them, which is why this package does not offer a `v8()` method. The `validate()` and `version()` methods do work with such UUIDs, however. | ||
### uuid.validate(str) | ||
|
||
Test a string to see if it is a valid UUID | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -82,6 +82,7 @@ For timestamp UUIDs, namespace UUIDs, and other options read on ... | |
| [`uuid.v6()`](#uuidv6options-buffer-offset) | Create a version 6 (timestamp, reordered) UUID | New in `uuid@10` | | ||
| [`uuid.v6ToV1()`](#uuidv6tov1uuid) | Create a version 1 UUID from a version 6 UUID | New in `uuid@10` | | ||
| [`uuid.v7()`](#uuidv7options-buffer-offset) | Create a version 7 (Unix Epoch time-based) UUID | New in `uuid@10` | | ||
| ~~[`uuid.v8()`](#uuidv8)~~ | "Intentionally left blank" | | | ||
| [`uuid.validate()`](#uuidvalidatestr) | Test a string to see if it is a valid UUID | New in `[email protected]` | | ||
| [`uuid.version()`](#uuidversionstr) | Detect RFC version of a UUID | New in `[email protected]` | | ||
|
||
|
@@ -361,6 +362,14 @@ import { v7 as uuidv7 } from 'uuid'; | |
uuidv7(); // RESULT | ||
``` | ||
|
||
### ~~uuid.v8()~~ | ||
|
||
**_"Intentionally left blank"_** | ||
|
||
<!-- prettier-ignore --> | ||
> [!NOTE] | ||
> Version 8 (experimental) UUIDs are "[for experimental or vendor-specific use cases](https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-8)". The RFC does not define a creation algorithm for them, which is why this package does not offer a `v8()` method. The `validate()` and `version()` methods do work with such UUIDs, however. | ||
### uuid.validate(str) | ||
|
||
Test a string to see if it is a valid UUID | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import MAX from '../../src/max.js'; | ||
import NIL from '../../src/nil.js'; | ||
|
||
// Table of [uuid value, expected validate(), [expected version()]] | ||
export const TESTS = [ | ||
// constants | ||
{ value: NIL, expectedValidate: true, expectedVersion: 0 }, | ||
{ value: MAX, expectedValidate: true, expectedVersion: 15 }, | ||
|
||
// each version, with either all 0's or all 1's in settable bits | ||
{ value: '00000000-0000-1000-8000-000000000000', expectedValidate: true, expectedVersion: 1 }, | ||
{ value: 'ffffffff-ffff-1fff-8fff-ffffffffffff', expectedValidate: true, expectedVersion: 1 }, | ||
{ value: '00000000-0000-2000-8000-000000000000', expectedValidate: true, expectedVersion: 2 }, | ||
{ value: 'ffffffff-ffff-2fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 2 }, | ||
{ value: '00000000-0000-3000-8000-000000000000', expectedValidate: true, expectedVersion: 3 }, | ||
{ value: 'ffffffff-ffff-3fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 3 }, | ||
{ value: '00000000-0000-4000-8000-000000000000', expectedValidate: true, expectedVersion: 4 }, | ||
{ value: 'ffffffff-ffff-4fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 4 }, | ||
{ value: '00000000-0000-5000-8000-000000000000', expectedValidate: true, expectedVersion: 5 }, | ||
{ value: 'ffffffff-ffff-5fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 5 }, | ||
{ value: '00000000-0000-6000-8000-000000000000', expectedValidate: true, expectedVersion: 6 }, | ||
{ value: 'ffffffff-ffff-6fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 6 }, | ||
{ value: '00000000-0000-7000-8000-000000000000', expectedValidate: true, expectedVersion: 7 }, | ||
{ value: 'ffffffff-ffff-7fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 7 }, | ||
{ value: '00000000-0000-8000-8000-000000000000', expectedValidate: true, expectedVersion: 8 }, | ||
{ value: 'ffffffff-ffff-8fff-bfff-ffffffffffff', expectedValidate: true, expectedVersion: 8 }, | ||
{ value: '00000000-0000-9000-8000-000000000000', expectedValidate: false }, | ||
{ value: 'ffffffff-ffff-9fff-bfff-ffffffffffff', expectedValidate: false }, | ||
{ value: '00000000-0000-a000-8000-000000000000', expectedValidate: false }, | ||
{ value: 'ffffffff-ffff-afff-bfff-ffffffffffff', expectedValidate: false }, | ||
{ value: '00000000-0000-b000-8000-000000000000', expectedValidate: false }, | ||
{ value: 'ffffffff-ffff-bfff-bfff-ffffffffffff', expectedValidate: false }, | ||
{ value: '00000000-0000-c000-8000-000000000000', expectedValidate: false }, | ||
{ value: 'ffffffff-ffff-cfff-bfff-ffffffffffff', expectedValidate: false }, | ||
{ value: '00000000-0000-d000-8000-000000000000', expectedValidate: false }, | ||
{ value: 'ffffffff-ffff-dfff-bfff-ffffffffffff', expectedValidate: false }, | ||
{ value: '00000000-0000-e000-8000-000000000000', expectedValidate: false }, | ||
{ value: 'ffffffff-ffff-efff-bfff-ffffffffffff', expectedValidate: false }, | ||
|
||
// selection of normal, valid UUIDs | ||
{ value: 'd9428888-122b-11e1-b85c-61cd3cbb3210', expectedValidate: true, expectedVersion: 1 }, | ||
{ value: '000003e8-2363-21ef-b200-325096b39f47', expectedValidate: true, expectedVersion: 2 }, | ||
{ value: 'a981a0c2-68b1-35dc-bcfc-296e52ab01ec', expectedValidate: true, expectedVersion: 3 }, | ||
{ value: '109156be-c4fb-41ea-b1b4-efe1671c5836', expectedValidate: true, expectedVersion: 4 }, | ||
{ value: '90123e1c-7512-523e-bb28-76fab9f2f73d', expectedValidate: true, expectedVersion: 5 }, | ||
{ value: '1ef21d2f-1207-6660-8c4f-419efbd44d48', expectedValidate: true, expectedVersion: 6 }, | ||
{ value: '017f22e2-79b0-7cc3-98c4-dc0c0c07398f', expectedValidate: true, expectedVersion: 7 }, | ||
{ value: '0d8f23a0-697f-83ae-802e-48f3756dd581', expectedValidate: true, expectedVersion: 8 }, | ||
|
||
// all variant octet values | ||
{ value: '00000000-0000-1000-0000-000000000000', expectedValidate: false }, | ||
{ value: '00000000-0000-1000-1000-000000000000', expectedValidate: false }, | ||
{ value: '00000000-0000-1000-2000-000000000000', expectedValidate: false }, | ||
{ value: '00000000-0000-1000-3000-000000000000', expectedValidate: false }, | ||
{ value: '00000000-0000-1000-4000-000000000000', expectedValidate: false }, | ||
{ value: '00000000-0000-1000-5000-000000000000', expectedValidate: false }, | ||
{ value: '00000000-0000-1000-6000-000000000000', expectedValidate: false }, | ||
{ value: '00000000-0000-1000-7000-000000000000', expectedValidate: false }, | ||
{ value: '00000000-0000-1000-8000-000000000000', expectedValidate: true, expectedVersion: 1 }, | ||
{ value: '00000000-0000-1000-9000-000000000000', expectedValidate: true, expectedVersion: 1 }, | ||
{ value: '00000000-0000-1000-a000-000000000000', expectedValidate: true, expectedVersion: 1 }, | ||
{ value: '00000000-0000-1000-b000-000000000000', expectedValidate: true, expectedVersion: 1 }, | ||
{ value: '00000000-0000-1000-c000-000000000000', expectedValidate: false }, | ||
{ value: '00000000-0000-1000-d000-000000000000', expectedValidate: false }, | ||
{ value: '00000000-0000-1000-e000-000000000000', expectedValidate: false }, | ||
{ value: '00000000-0000-1000-f000-000000000000', expectedValidate: false }, | ||
|
||
// invalid strings | ||
{ value: '00000000000000000000000000000000', expectedValidate: false }, // unhyphenated NIL | ||
{ value: '', expectedValidate: false }, | ||
{ value: 'invalid uuid string', expectedValidate: false }, | ||
{ | ||
value: '=Y00a-f*vb*-c-d#-p00f\b-g0h-#i^-j*3&-L00k-\nl---00n-fg000-00p-00r+', | ||
expectedValidate: false, | ||
}, | ||
|
||
// invalid types | ||
{ value: undefined, expectedValidate: false }, | ||
{ value: null, expectedValidate: false }, | ||
{ value: 123, expectedValidate: false }, | ||
{ value: /regex/, expectedValidate: false }, | ||
{ value: new Date(0), expectedValidate: false }, | ||
{ value: false, expectedValidate: false }, | ||
]; | ||
|
||
// Add NIL and MAX UUIDs with 1-bit flipped in each position | ||
for (let charIndex = 0; charIndex < 36; charIndex++) { | ||
// Skip hyphens and version char | ||
if ( | ||
charIndex === 8 || | ||
charIndex === 13 || | ||
charIndex === 14 || // version char | ||
charIndex === 18 || | ||
charIndex === 23 | ||
) { | ||
continue; | ||
} | ||
|
||
const nilChars = NIL.split(''); | ||
const maxChars = MAX.split(''); | ||
|
||
for (let i = 0; i < 4; i++) { | ||
nilChars[charIndex] = (0x0 ^ (1 << i)).toString(16); | ||
// NIL UUIDs w/ a single 1-bit | ||
TESTS.push({ value: nilChars.join(''), expectedValidate: false }); | ||
|
||
// MAX UUIDs w/ a single 0-bit | ||
maxChars[charIndex] = (0xf ^ (1 << i)).toString(16); | ||
TESTS.push({ value: maxChars.join(''), expectedValidate: false }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,72 +1,15 @@ | ||
import assert from 'assert'; | ||
import MAX from '../../src/max.js'; | ||
import NIL from '../../src/nil.js'; | ||
import validate from '../../src/validate.js'; | ||
import { TESTS } from './test_constants.js'; | ||
|
||
describe('validate', () => { | ||
test('validate uuid', () => { | ||
assert.strictEqual(validate(NIL), true); | ||
assert.strictEqual(validate(MAX), true); | ||
|
||
// test valid UUID versions | ||
|
||
// v1 | ||
assert.strictEqual(validate('d9428888-122b-11e1-b85c-61cd3cbb3210'), true); | ||
|
||
// v3 | ||
assert.strictEqual(validate('a981a0c2-68b1-35dc-bcfc-296e52ab01ec'), true); | ||
|
||
// v4 | ||
assert.strictEqual(validate('109156be-c4fb-41ea-b1b4-efe1671c5836'), true); | ||
|
||
// v5 | ||
assert.strictEqual(validate('90123e1c-7512-523e-bb28-76fab9f2f73d'), true); | ||
|
||
// v6 | ||
assert.strictEqual(validate('1ef21d2f-1207-6660-8c4f-419efbd44d48'), true); | ||
|
||
// v7 | ||
assert.strictEqual(validate('017f22e2-79b0-7cc3-98c4-dc0c0c07398f'), true); | ||
|
||
// test invalid/unsupported UUID versions | ||
[0, 2, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f'].forEach((v) => { | ||
describe('validate() tests', () => { | ||
test('TESTS cases', () => { | ||
for (const { value, expectedValidate } of TESTS) { | ||
assert.strictEqual( | ||
validate('12300000-0000-' + v + '000-0000-000000000000'), | ||
false, | ||
'version ' + v + ' should not be valid' | ||
validate(value), | ||
expectedValidate, | ||
`validate(${value}) should be ${expectedValidate}` | ||
); | ||
}); | ||
|
||
assert.strictEqual(validate(), false); | ||
|
||
assert.strictEqual(validate(''), false); | ||
|
||
assert.strictEqual(validate('invalid uuid string'), false); | ||
|
||
assert.strictEqual(validate('00000000000000000000000000000000'), false); | ||
|
||
// NIL UUIDs that have a bit set (incorrectly) should not validate | ||
for (let charIndex = 0; charIndex < 36; charIndex++) { | ||
if (charIndex === 14) { | ||
continue; | ||
} // version field | ||
|
||
for (let bit = 0; bit < 4; bit++) { | ||
const chars = NIL.split(''); | ||
if (chars[charIndex] === '-') { | ||
continue; | ||
} | ||
|
||
chars[charIndex] = (1 << bit).toString(16); | ||
assert.strictEqual(validate(chars.join('')), false); | ||
} | ||
} | ||
|
||
assert.strictEqual( | ||
validate( | ||
'=Y00a-f*v00b*-00c-00d#-p00f\b-00g-00h-####00i^^^-00j*1*2*3&-L00k-\n00l-/00m-----00n-fg000-00p-00r+' | ||
), | ||
false | ||
); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,17 @@ | ||
import assert from 'assert'; | ||
import MAX from '../../src/max.js'; | ||
import NIL from '../../src/nil.js'; | ||
import version from '../../src/version.js'; | ||
import { TESTS } from './test_constants.js'; | ||
|
||
describe('version', () => { | ||
test('check uuid version', () => { | ||
assert.strictEqual(version(NIL), 0); | ||
assert.strictEqual(version(MAX), 15); | ||
|
||
assert.strictEqual(version('d9428888-122b-11e1-b85c-61cd3cbb3210'), 1); | ||
assert.strictEqual(version('a981a0c2-68b1-35dc-bcfc-296e52ab01ec'), 3); | ||
assert.strictEqual(version('109156be-c4fb-41ea-b1b4-efe1671c5836'), 4); | ||
assert.strictEqual(version('90123e1c-7512-523e-bb28-76fab9f2f73d'), 5); | ||
assert.strictEqual(version('1ef21d2f-1207-6660-8c4f-419efbd44d48'), 6); | ||
assert.strictEqual(version('017f22e2-79b0-7cc3-98c4-dc0c0c07398f'), 7); | ||
|
||
assert.throws(() => version()); | ||
assert.throws(() => version('')); | ||
assert.throws(() => version('invalid uuid string')); | ||
assert.throws(() => version('00000000000000000000000000000000')); | ||
assert.throws(() => version('=Y00a-f*v00b*-00c-00d#-p00f\b-00g-00h-##0p-00r+')); | ||
describe('version() tests', () => { | ||
test('TESTS cases', () => { | ||
for (const { value, expectedValidate, expectedVersion } of TESTS) { | ||
try { | ||
const actualVersion = version(value); | ||
assert(expectedValidate, `version(${value}) should throw`); | ||
assert.strictEqual(actualVersion, expectedVersion); | ||
} catch (err) { | ||
assert(!expectedValidate, `version(${value}) threw unexpectedly`); | ||
} | ||
} | ||
}); | ||
}); |