summaryrefslogtreecommitdiffstats
path: root/tests/fix_crdb.py
blob: 88ab50419ea1b020381faed546488693e1f1a9d3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
from typing import Optional

import pytest

from .utils import VersionCheck
from psycopg.crdb import CrdbConnection


def pytest_configure(config):
    # register libpq marker
    config.addinivalue_line(
        "markers",
        "crdb(version_expr, reason=detail): run/skip the test with matching CockroachDB"
        " (e.g. '>= 21.2.10', '< 22.1', 'skip < 22')",
    )
    config.addinivalue_line(
        "markers",
        "crdb_skip(reason): skip the test for known CockroachDB reasons",
    )


def check_crdb_version(got, mark):
    if mark.name == "crdb":
        assert len(mark.args) <= 1
        assert not (set(mark.kwargs) - {"reason"})
        spec = mark.args[0] if mark.args else "only"
        reason = mark.kwargs.get("reason")
    elif mark.name == "crdb_skip":
        assert len(mark.args) == 1
        assert not mark.kwargs
        reason = mark.args[0]
        assert reason in _crdb_reasons, reason
        spec = _crdb_reason_version.get(reason, "skip")
    else:
        assert False, mark.name

    pred = VersionCheck.parse(spec)
    pred.whose = "CockroachDB"

    msg = pred.get_skip_message(got)
    if not msg:
        return None

    reason = crdb_skip_message(reason)
    if reason:
        msg = f"{msg}: {reason}"

    return msg


# Utility functions which can be imported in the test suite

is_crdb = CrdbConnection.is_crdb


def crdb_skip_message(reason: Optional[str]) -> str:
    msg = ""
    if reason:
        msg = reason
        if _crdb_reasons.get(reason):
            url = (
                "https://github.com/cockroachdb/cockroach/"
                f"issues/{_crdb_reasons[reason]}"
            )
            msg = f"{msg} ({url})"

    return msg


def skip_crdb(*args, reason=None):
    return pytest.param(*args, marks=pytest.mark.crdb("skip", reason=reason))


def crdb_encoding(*args):
    """Mark tests that fail on CockroachDB because of missing encodings"""
    return skip_crdb(*args, reason="encoding")


def crdb_time_precision(*args):
    """Mark tests that fail on CockroachDB because time doesn't support precision"""
    return skip_crdb(*args, reason="time precision")


def crdb_scs_off(*args):
    return skip_crdb(*args, reason="standard_conforming_strings=off")


# mapping from reason description to ticket number
_crdb_reasons = {
    "2-phase commit": 22329,
    "backend pid": 35897,
    "batch statements": 44803,
    "begin_read_only": 87012,
    "binary decimal": 82492,
    "cancel": 41335,
    "cast adds tz": 51692,
    "cidr": 18846,
    "composite": 27792,
    "copy array": 82792,
    "copy canceled": 81559,
    "copy": 41608,
    "cursor invalid name": 84261,
    "cursor with hold": 77101,
    "deferrable": 48307,
    "do": 17511,
    "encoding": 35882,
    "geometric types": 21286,
    "hstore": 41284,
    "infinity date": 41564,
    "interval style": 35807,
    "json array": 23468,
    "large objects": 243,
    "negative interval": 81577,
    "nested array": 32552,
    "no col query": None,
    "notify": 41522,
    "password_encryption": 42519,
    "pg_terminate_backend": 35897,
    "range": 41282,
    "scroll cursor": 77102,
    "server-side cursor": 41412,
    "severity_nonlocalized": 81794,
    "stored procedure": 1751,
}

_crdb_reason_version = {
    "backend pid": "skip < 22",
    "cancel": "skip < 22",
    "server-side cursor": "skip < 22.1.3",
    "severity_nonlocalized": "skip < 22.1.3",
}