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

Test suite #11

Closed
MrZoidberg opened this issue Oct 17, 2021 · 4 comments
Closed

Test suite #11

MrZoidberg opened this issue Oct 17, 2021 · 4 comments

Comments

@MrZoidberg
Copy link

I'm implementing a C# version of UUIDv7 and it looks like I have some problems with my implementation. It would be great to have a common list of tests to check the implementation.

kyzer-davis added a commit that referenced this issue Dec 30, 2021
@kyzer-davis kyzer-davis linked a pull request Dec 30, 2021 that will close this issue
@kyzer-davis kyzer-davis removed a link to a pull request Dec 30, 2021
@kyzer-davis
Copy link
Collaborator

Not enough Coffee! I didn't merge anything for this issue. I was trying to merge changes for #8 sorry for the notifications.

I also see uuid6/uuid6-ietf-draft#43

I am open to Test Vectors but I don't have the cycles at the moment to work through them.
PRs are welcome on the Python implementation on this page.

@oittaa
Copy link
Contributor

oittaa commented Jan 2, 2022

import secrets
import time


def _subsec_decode(value: int, subsec_bits: int, subsec_decimal_digits: int) -> int:
    return -(-value * 10 ** subsec_decimal_digits // 2 ** subsec_bits)


def _subsec_encode(value: int, subsec_bits: int, subsec_decimal_digits: int) -> int:
    return value * 2 ** subsec_bits // 10 ** subsec_decimal_digits


def uuid7(
    unixts: int = None,
    subsec: int = None,
    seq: int = None,
    node: int = None,
    subsec_bits: int = 30,
    subsec_digits: int = 9,
    seq_bits: int = 0,
) -> str:
    """UUIDv7 draft 02"""

    node_bits = 86 - subsec_bits - seq_bits
    # sanity checks
    if subsec_bits < 0 or seq_bits < 0 or node_bits < 0:
        raise ValueError("invalid bit value")
    if unixts is None or subsec is None:
        if unixts is not None or subsec is not None:
            raise ValueError("both unixts and subsec need to be set or unset")
        if subsec_digits != 9:
            raise ValueError("invalid subsec_digits")
        unixts, subsec = divmod(time.time_ns(), 10 ** 9)
    if unixts < 0:
        raise ValueError("unixts needs to be greater than or equal to 0")
    if subsec < 0:
        raise ValueError("subsec needs to be greater than or equal to 0")
    if subsec >= 10 ** subsec_digits:
        raise ValueError("subsec overflow")
    if seq is not None:
        if seq < 0:
            raise ValueError("seq needs to be greater than or equal to 0")
        if seq >= 2 ** seq_bits:
            raise ValueError("seq overflow")
    if node is not None:
        if node <= 0:
            raise ValueError("node needs to be greater than 0")
        if node >= 2 ** node_bits:
            raise ValueError("node overflow")

    subsec_seq_node = _subsec_encode(subsec, subsec_bits, subsec_digits) << (
        node_bits + seq_bits
    )
    if seq:
        subsec_seq_node |= seq << node_bits
    if node_bits:
        while node is None or node == 0:
            node = secrets.randbits(node_bits)
        subsec_seq_node |= node
    subsec_a = subsec_seq_node >> 74
    subsec_b = (subsec_seq_node >> 62) & 0x0FFF

    uuid_int = (unixts & 0x0FFFFFFFFF) << 92
    uuid_int |= subsec_a << 80
    uuid_int |= subsec_b << 64
    uuid_int |= subsec_seq_node & 0x03FFFFFFFFFFFFFFF
    # Set the variant to RFC 4122.
    uuid_int |= 0x8000 << 48
    # Set the version number.
    uuid_int |= 7 << 76

    uuid_hex = "%032x" % uuid_int
    return "%s-%s-%s-%s-%s" % (
        uuid_hex[:8],
        uuid_hex[8:12],
        uuid_hex[12:16],
        uuid_hex[16:20],
        uuid_hex[20:],
    )

I haven't tested this thoroughly, but if there aren't any major bugs, you can pretty easily input whatever you want for unixts, subsec, and so on. Without any parameters the current time is used and a random node is generated with secrets.randbits().

>>> uuid7(123, 456, 78, 9, seq_bits=8)
'00000007-b000-7007-a94e-000000000009'
>>> uuid7()
'061d1ff8-cd61-7a60-b546-3746d11b885d'

@oittaa
Copy link
Contributor

oittaa commented Jan 3, 2022

I've generated some test vectors with the following snippet. What do you guys think about it?

def generate_test_vectors():
    for subsec_bits in (10, 12, 20, 24, 30, 40):
        for subsec_digits in range(3, 13):
            print(f"### {subsec_bits=}, {subsec_digits=}")
            for unixts in (0, 1, 2, 2 ** 35, 2 ** 36 - 1):
                for subsec in (
                    0,
                    1,
                    2,
                    10 ** subsec_digits // 2 - 1,
                    10 ** subsec_digits // 2,
                    10 ** subsec_digits - 2,
                    10 ** subsec_digits - 1,
                ):
                    for node in (
                        1,
                        2,
                        2 ** (86 - subsec_bits) - 2,
                        2 ** (86 - subsec_bits) - 1,
                    ):
                        value = uuid7(
                            unixts,
                            subsec,
                            node=node,
                            subsec_bits=subsec_bits,
                            subsec_digits=subsec_digits,
                        )
                        print(f"{unixts=}, {subsec=}, {node=} = {value}")

Part of the output that covers the common(?) nanosecond case, which requires 30 bits to represent it.

### subsec_bits=30, subsec_digits=9
unixts=0, subsec=0, node=1 = 00000000-0000-7000-8000-000000000001
unixts=0, subsec=0, node=2 = 00000000-0000-7000-8000-000000000002
unixts=0, subsec=0, node=72057594037927934 = 00000000-0000-7000-80ff-fffffffffffe
unixts=0, subsec=0, node=72057594037927935 = 00000000-0000-7000-80ff-ffffffffffff
unixts=0, subsec=1, node=1 = 00000000-0000-7000-8100-000000000001
unixts=0, subsec=1, node=2 = 00000000-0000-7000-8100-000000000002
unixts=0, subsec=1, node=72057594037927934 = 00000000-0000-7000-81ff-fffffffffffe
unixts=0, subsec=1, node=72057594037927935 = 00000000-0000-7000-81ff-ffffffffffff
unixts=0, subsec=2, node=1 = 00000000-0000-7000-8200-000000000001
unixts=0, subsec=2, node=2 = 00000000-0000-7000-8200-000000000002
unixts=0, subsec=2, node=72057594037927934 = 00000000-0000-7000-82ff-fffffffffffe
unixts=0, subsec=2, node=72057594037927935 = 00000000-0000-7000-82ff-ffffffffffff
unixts=0, subsec=499999999, node=1 = 00000000-07ff-7fff-be00-000000000001
unixts=0, subsec=499999999, node=2 = 00000000-07ff-7fff-be00-000000000002
unixts=0, subsec=499999999, node=72057594037927934 = 00000000-07ff-7fff-beff-fffffffffffe
unixts=0, subsec=499999999, node=72057594037927935 = 00000000-07ff-7fff-beff-ffffffffffff
unixts=0, subsec=500000000, node=1 = 00000000-0800-7000-8000-000000000001
unixts=0, subsec=500000000, node=2 = 00000000-0800-7000-8000-000000000002
unixts=0, subsec=500000000, node=72057594037927934 = 00000000-0800-7000-80ff-fffffffffffe
unixts=0, subsec=500000000, node=72057594037927935 = 00000000-0800-7000-80ff-ffffffffffff
unixts=0, subsec=999999998, node=1 = 00000000-0fff-7fff-bd00-000000000001
unixts=0, subsec=999999998, node=2 = 00000000-0fff-7fff-bd00-000000000002
unixts=0, subsec=999999998, node=72057594037927934 = 00000000-0fff-7fff-bdff-fffffffffffe
unixts=0, subsec=999999998, node=72057594037927935 = 00000000-0fff-7fff-bdff-ffffffffffff
unixts=0, subsec=999999999, node=1 = 00000000-0fff-7fff-be00-000000000001
unixts=0, subsec=999999999, node=2 = 00000000-0fff-7fff-be00-000000000002
unixts=0, subsec=999999999, node=72057594037927934 = 00000000-0fff-7fff-beff-fffffffffffe
unixts=0, subsec=999999999, node=72057594037927935 = 00000000-0fff-7fff-beff-ffffffffffff
unixts=1, subsec=0, node=1 = 00000000-1000-7000-8000-000000000001
unixts=1, subsec=0, node=2 = 00000000-1000-7000-8000-000000000002
unixts=1, subsec=0, node=72057594037927934 = 00000000-1000-7000-80ff-fffffffffffe
unixts=1, subsec=0, node=72057594037927935 = 00000000-1000-7000-80ff-ffffffffffff
unixts=1, subsec=1, node=1 = 00000000-1000-7000-8100-000000000001
unixts=1, subsec=1, node=2 = 00000000-1000-7000-8100-000000000002
unixts=1, subsec=1, node=72057594037927934 = 00000000-1000-7000-81ff-fffffffffffe
unixts=1, subsec=1, node=72057594037927935 = 00000000-1000-7000-81ff-ffffffffffff
unixts=1, subsec=2, node=1 = 00000000-1000-7000-8200-000000000001
unixts=1, subsec=2, node=2 = 00000000-1000-7000-8200-000000000002
unixts=1, subsec=2, node=72057594037927934 = 00000000-1000-7000-82ff-fffffffffffe
unixts=1, subsec=2, node=72057594037927935 = 00000000-1000-7000-82ff-ffffffffffff
unixts=1, subsec=499999999, node=1 = 00000000-17ff-7fff-be00-000000000001
unixts=1, subsec=499999999, node=2 = 00000000-17ff-7fff-be00-000000000002
unixts=1, subsec=499999999, node=72057594037927934 = 00000000-17ff-7fff-beff-fffffffffffe
unixts=1, subsec=499999999, node=72057594037927935 = 00000000-17ff-7fff-beff-ffffffffffff
unixts=1, subsec=500000000, node=1 = 00000000-1800-7000-8000-000000000001
unixts=1, subsec=500000000, node=2 = 00000000-1800-7000-8000-000000000002
unixts=1, subsec=500000000, node=72057594037927934 = 00000000-1800-7000-80ff-fffffffffffe
unixts=1, subsec=500000000, node=72057594037927935 = 00000000-1800-7000-80ff-ffffffffffff
unixts=1, subsec=999999998, node=1 = 00000000-1fff-7fff-bd00-000000000001
unixts=1, subsec=999999998, node=2 = 00000000-1fff-7fff-bd00-000000000002
unixts=1, subsec=999999998, node=72057594037927934 = 00000000-1fff-7fff-bdff-fffffffffffe
unixts=1, subsec=999999998, node=72057594037927935 = 00000000-1fff-7fff-bdff-ffffffffffff
unixts=1, subsec=999999999, node=1 = 00000000-1fff-7fff-be00-000000000001
unixts=1, subsec=999999999, node=2 = 00000000-1fff-7fff-be00-000000000002
unixts=1, subsec=999999999, node=72057594037927934 = 00000000-1fff-7fff-beff-fffffffffffe
unixts=1, subsec=999999999, node=72057594037927935 = 00000000-1fff-7fff-beff-ffffffffffff
unixts=2, subsec=0, node=1 = 00000000-2000-7000-8000-000000000001
unixts=2, subsec=0, node=2 = 00000000-2000-7000-8000-000000000002
unixts=2, subsec=0, node=72057594037927934 = 00000000-2000-7000-80ff-fffffffffffe
unixts=2, subsec=0, node=72057594037927935 = 00000000-2000-7000-80ff-ffffffffffff
unixts=2, subsec=1, node=1 = 00000000-2000-7000-8100-000000000001
unixts=2, subsec=1, node=2 = 00000000-2000-7000-8100-000000000002
unixts=2, subsec=1, node=72057594037927934 = 00000000-2000-7000-81ff-fffffffffffe
unixts=2, subsec=1, node=72057594037927935 = 00000000-2000-7000-81ff-ffffffffffff
unixts=2, subsec=2, node=1 = 00000000-2000-7000-8200-000000000001
unixts=2, subsec=2, node=2 = 00000000-2000-7000-8200-000000000002
unixts=2, subsec=2, node=72057594037927934 = 00000000-2000-7000-82ff-fffffffffffe
unixts=2, subsec=2, node=72057594037927935 = 00000000-2000-7000-82ff-ffffffffffff
unixts=2, subsec=499999999, node=1 = 00000000-27ff-7fff-be00-000000000001
unixts=2, subsec=499999999, node=2 = 00000000-27ff-7fff-be00-000000000002
unixts=2, subsec=499999999, node=72057594037927934 = 00000000-27ff-7fff-beff-fffffffffffe
unixts=2, subsec=499999999, node=72057594037927935 = 00000000-27ff-7fff-beff-ffffffffffff
unixts=2, subsec=500000000, node=1 = 00000000-2800-7000-8000-000000000001
unixts=2, subsec=500000000, node=2 = 00000000-2800-7000-8000-000000000002
unixts=2, subsec=500000000, node=72057594037927934 = 00000000-2800-7000-80ff-fffffffffffe
unixts=2, subsec=500000000, node=72057594037927935 = 00000000-2800-7000-80ff-ffffffffffff
unixts=2, subsec=999999998, node=1 = 00000000-2fff-7fff-bd00-000000000001
unixts=2, subsec=999999998, node=2 = 00000000-2fff-7fff-bd00-000000000002
unixts=2, subsec=999999998, node=72057594037927934 = 00000000-2fff-7fff-bdff-fffffffffffe
unixts=2, subsec=999999998, node=72057594037927935 = 00000000-2fff-7fff-bdff-ffffffffffff
unixts=2, subsec=999999999, node=1 = 00000000-2fff-7fff-be00-000000000001
unixts=2, subsec=999999999, node=2 = 00000000-2fff-7fff-be00-000000000002
unixts=2, subsec=999999999, node=72057594037927934 = 00000000-2fff-7fff-beff-fffffffffffe
unixts=2, subsec=999999999, node=72057594037927935 = 00000000-2fff-7fff-beff-ffffffffffff
unixts=34359738368, subsec=0, node=1 = 80000000-0000-7000-8000-000000000001
unixts=34359738368, subsec=0, node=2 = 80000000-0000-7000-8000-000000000002
unixts=34359738368, subsec=0, node=72057594037927934 = 80000000-0000-7000-80ff-fffffffffffe
unixts=34359738368, subsec=0, node=72057594037927935 = 80000000-0000-7000-80ff-ffffffffffff
unixts=34359738368, subsec=1, node=1 = 80000000-0000-7000-8100-000000000001
unixts=34359738368, subsec=1, node=2 = 80000000-0000-7000-8100-000000000002
unixts=34359738368, subsec=1, node=72057594037927934 = 80000000-0000-7000-81ff-fffffffffffe
unixts=34359738368, subsec=1, node=72057594037927935 = 80000000-0000-7000-81ff-ffffffffffff
unixts=34359738368, subsec=2, node=1 = 80000000-0000-7000-8200-000000000001
unixts=34359738368, subsec=2, node=2 = 80000000-0000-7000-8200-000000000002
unixts=34359738368, subsec=2, node=72057594037927934 = 80000000-0000-7000-82ff-fffffffffffe
unixts=34359738368, subsec=2, node=72057594037927935 = 80000000-0000-7000-82ff-ffffffffffff
unixts=34359738368, subsec=499999999, node=1 = 80000000-07ff-7fff-be00-000000000001
unixts=34359738368, subsec=499999999, node=2 = 80000000-07ff-7fff-be00-000000000002
unixts=34359738368, subsec=499999999, node=72057594037927934 = 80000000-07ff-7fff-beff-fffffffffffe
unixts=34359738368, subsec=499999999, node=72057594037927935 = 80000000-07ff-7fff-beff-ffffffffffff
unixts=34359738368, subsec=500000000, node=1 = 80000000-0800-7000-8000-000000000001
unixts=34359738368, subsec=500000000, node=2 = 80000000-0800-7000-8000-000000000002
unixts=34359738368, subsec=500000000, node=72057594037927934 = 80000000-0800-7000-80ff-fffffffffffe
unixts=34359738368, subsec=500000000, node=72057594037927935 = 80000000-0800-7000-80ff-ffffffffffff
unixts=34359738368, subsec=999999998, node=1 = 80000000-0fff-7fff-bd00-000000000001
unixts=34359738368, subsec=999999998, node=2 = 80000000-0fff-7fff-bd00-000000000002
unixts=34359738368, subsec=999999998, node=72057594037927934 = 80000000-0fff-7fff-bdff-fffffffffffe
unixts=34359738368, subsec=999999998, node=72057594037927935 = 80000000-0fff-7fff-bdff-ffffffffffff
unixts=34359738368, subsec=999999999, node=1 = 80000000-0fff-7fff-be00-000000000001
unixts=34359738368, subsec=999999999, node=2 = 80000000-0fff-7fff-be00-000000000002
unixts=34359738368, subsec=999999999, node=72057594037927934 = 80000000-0fff-7fff-beff-fffffffffffe
unixts=34359738368, subsec=999999999, node=72057594037927935 = 80000000-0fff-7fff-beff-ffffffffffff
unixts=68719476735, subsec=0, node=1 = ffffffff-f000-7000-8000-000000000001
unixts=68719476735, subsec=0, node=2 = ffffffff-f000-7000-8000-000000000002
unixts=68719476735, subsec=0, node=72057594037927934 = ffffffff-f000-7000-80ff-fffffffffffe
unixts=68719476735, subsec=0, node=72057594037927935 = ffffffff-f000-7000-80ff-ffffffffffff
unixts=68719476735, subsec=1, node=1 = ffffffff-f000-7000-8100-000000000001
unixts=68719476735, subsec=1, node=2 = ffffffff-f000-7000-8100-000000000002
unixts=68719476735, subsec=1, node=72057594037927934 = ffffffff-f000-7000-81ff-fffffffffffe
unixts=68719476735, subsec=1, node=72057594037927935 = ffffffff-f000-7000-81ff-ffffffffffff
unixts=68719476735, subsec=2, node=1 = ffffffff-f000-7000-8200-000000000001
unixts=68719476735, subsec=2, node=2 = ffffffff-f000-7000-8200-000000000002
unixts=68719476735, subsec=2, node=72057594037927934 = ffffffff-f000-7000-82ff-fffffffffffe
unixts=68719476735, subsec=2, node=72057594037927935 = ffffffff-f000-7000-82ff-ffffffffffff
unixts=68719476735, subsec=499999999, node=1 = ffffffff-f7ff-7fff-be00-000000000001
unixts=68719476735, subsec=499999999, node=2 = ffffffff-f7ff-7fff-be00-000000000002
unixts=68719476735, subsec=499999999, node=72057594037927934 = ffffffff-f7ff-7fff-beff-fffffffffffe
unixts=68719476735, subsec=499999999, node=72057594037927935 = ffffffff-f7ff-7fff-beff-ffffffffffff
unixts=68719476735, subsec=500000000, node=1 = ffffffff-f800-7000-8000-000000000001
unixts=68719476735, subsec=500000000, node=2 = ffffffff-f800-7000-8000-000000000002
unixts=68719476735, subsec=500000000, node=72057594037927934 = ffffffff-f800-7000-80ff-fffffffffffe
unixts=68719476735, subsec=500000000, node=72057594037927935 = ffffffff-f800-7000-80ff-ffffffffffff
unixts=68719476735, subsec=999999998, node=1 = ffffffff-ffff-7fff-bd00-000000000001
unixts=68719476735, subsec=999999998, node=2 = ffffffff-ffff-7fff-bd00-000000000002
unixts=68719476735, subsec=999999998, node=72057594037927934 = ffffffff-ffff-7fff-bdff-fffffffffffe
unixts=68719476735, subsec=999999998, node=72057594037927935 = ffffffff-ffff-7fff-bdff-ffffffffffff
unixts=68719476735, subsec=999999999, node=1 = ffffffff-ffff-7fff-be00-000000000001
unixts=68719476735, subsec=999999999, node=2 = ffffffff-ffff-7fff-be00-000000000002
unixts=68719476735, subsec=999999999, node=72057594037927934 = ffffffff-ffff-7fff-beff-fffffffffffe
unixts=68719476735, subsec=999999999, node=72057594037927935 = ffffffff-ffff-7fff-beff-ffffffffffff

@kyzer-davis
Copy link
Collaborator

@oittaa, I put this on hold because of some changes in Draft 03.
I also took your feedback and added an Appendix to the RFC Draft with a single test vector detailing UUIDv1 vs UUIDv6, UUIDv7 and a UUIDv8 sample.

If you could take a look at the latest Draft 03 PR that would be great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants