File: test_history_sqlite.py

package info (click to toggle)
xonsh 0.13.4%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 4,024 kB
  • sloc: python: 46,350; makefile: 136; sh: 41; xml: 17
file content (303 lines) | stat: -rw-r--r-- 9,239 bytes parent folder | download
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
"""Tests the xonsh history."""
# pylint: disable=protected-access
import os
import shlex

import pytest

from xonsh.history.main import history_main
from xonsh.history.sqlite import SqliteHistory


@pytest.fixture
def hist():
    h = SqliteHistory(
        filename="xonsh-HISTORY-TEST.sqlite", sessionid="SESSIONID", gc=False
    )
    yield h
    os.remove(h.filename)


def test_hist_append(hist, xession):
    """Verify appending to the history works."""
    xession.env["HISTCONTROL"] = set()
    hf = hist.append({"inp": "still alive", "rtn": 1})
    assert hf is None
    items = list(hist.items())
    assert len(items) == 1
    assert "still alive" == items[0]["inp"]
    assert 1 == items[0]["rtn"]
    hist.append({"inp": "still alive", "rtn": 0})
    items = list(hist.items())
    assert len(items) == 2
    assert "still alive" == items[1]["inp"]
    assert 0 == items[1]["rtn"]
    assert list(hist.all_items()) == items


def test_hist_attrs(hist, xession):
    xession.env["HISTCONTROL"] = set()
    hf = hist.append({"inp": "ls foo", "rtn": 1})
    assert hf is None
    assert "ls foo" == hist.inps[0]
    assert "ls foo" == hist.inps[-1]
    assert 1 == hist.rtns[0]
    assert 1 == hist.rtns[-1]
    assert None is hist.outs[-1]
    assert [1] == hist.rtns[:]
    hist.append({"inp": "ls bar", "rtn": 0})
    assert "ls bar" == hist.inps[1]
    assert "ls bar" == hist.inps[-1]
    assert 0 == hist.rtns[1]
    assert 0 == hist.rtns[-1]
    assert None is hist.outs[-1]
    assert [1, 0] == hist.rtns[:]
    assert len(hist.tss) == 2
    assert len(hist.tss[0]) == 2


CMDS = ["ls", "cat hello kitty", "abc", "def", "touch me", "grep from me"]


@pytest.mark.parametrize(
    "inp, commands, offset",
    [
        ("", CMDS, (0, 1)),
        ("-r", list(reversed(CMDS)), (len(CMDS) - 1, -1)),
        ("0", CMDS[0:1], (0, 1)),
        ("1", CMDS[1:2], (1, 1)),
        ("-2", CMDS[-2:-1], (len(CMDS) - 2, 1)),
        ("1:3", CMDS[1:3], (1, 1)),
        ("1::2", CMDS[1::2], (1, 2)),
        ("-4:-2", CMDS[-4:-2], (len(CMDS) - 4, 1)),
    ],
)
def test_show_cmd_numerate(inp, commands, offset, hist, xession, capsys):
    """Verify that CLI history commands work."""
    base_idx, step = offset
    xession.history = hist
    xession.env["HISTCONTROL"] = set()
    for ts, cmd in enumerate(CMDS):  # populate the shell history
        hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})

    exp = (f"{base_idx + idx * step}: {cmd}" for idx, cmd in enumerate(list(commands)))
    exp = "\n".join(exp)

    history_main(["show", "-n"] + shlex.split(inp))
    out, err = capsys.readouterr()
    assert out.rstrip() == exp


def test_histcontrol(hist, xession):
    """Test HISTCONTROL=ignoredups,ignoreerr"""

    ignore_opts = ",".join(["ignoredups", "ignoreerr", "ignorespace"])
    xession.env["HISTCONTROL"] = ignore_opts
    assert len(hist) == 0

    # An error, items() remains empty
    hist.append({"inp": "ls foo", "rtn": 2})
    assert len(hist) == 0
    assert len(hist.inps) == 1
    assert len(hist.rtns) == 1
    assert 2 == hist.rtns[-1]

    # Success
    hist.append({"inp": "ls foobazz", "rtn": 0})
    assert len(hist) == 1
    assert len(hist.inps) == 2
    assert len(hist.rtns) == 2
    items = list(hist.items())
    assert "ls foobazz" == items[-1]["inp"]
    assert 0 == items[-1]["rtn"]
    assert 0 == hist.rtns[-1]

    # Error
    hist.append({"inp": "ls foo", "rtn": 2})
    assert len(hist) == 1
    items = list(hist.items())
    assert "ls foobazz" == items[-1]["inp"]
    assert 0 == items[-1]["rtn"]
    assert 2 == hist.rtns[-1]

    # File now exists, success
    hist.append({"inp": "ls foo", "rtn": 0})
    assert len(hist) == 2
    items = list(hist.items())
    assert "ls foo" == items[-1]["inp"]
    assert 0 == items[-1]["rtn"]
    assert 0 == hist.rtns[-1]

    # Success
    hist.append({"inp": "ls", "rtn": 0})
    assert len(hist) == 3
    items = list(hist.items())
    assert "ls" == items[-1]["inp"]
    assert 0 == items[-1]["rtn"]
    assert 0 == hist.rtns[-1]

    # Dup
    hist.append({"inp": "ls", "rtn": 0})
    assert len(hist) == 3

    # Success
    hist.append({"inp": "/bin/ls", "rtn": 0})
    assert len(hist) == 4
    items = list(hist.items())
    assert "/bin/ls" == items[-1]["inp"]
    assert 0 == items[-1]["rtn"]
    assert 0 == hist.rtns[-1]

    # Error
    hist.append({"inp": "ls bazz", "rtn": 1})
    assert len(hist) == 4
    items = list(hist.items())
    assert "/bin/ls" == items[-1]["inp"]
    assert 0 == items[-1]["rtn"]
    assert "ls bazz" == hist.inps[-1]
    assert 1 == hist.rtns[-1]

    # Error
    hist.append({"inp": "ls bazz", "rtn": -1})
    assert len(hist) == 4
    items = list(hist.items())
    assert "/bin/ls" == items[-1]["inp"]
    assert 0 == items[-1]["rtn"]
    assert -1 == hist.rtns[-1]

    # Success
    hist.append({"inp": "echo not secret", "rtn": 0, "spc": False})
    assert len(hist) == 5
    items = list(hist.items())
    assert "echo not secret" == items[-1]["inp"]
    assert 0 == items[-1]["rtn"]
    assert 0 == hist.rtns[-1]

    # Space
    hist.append({"inp": "echo secret command", "rtn": 0, "spc": True})
    assert len(hist) == 5
    items = list(hist.items())
    assert "echo not secret" == items[-1]["inp"]
    assert 0 == items[-1]["rtn"]
    assert 0 == hist.rtns[-1]


def test_histcontrol_erase_dup(hist, xession):
    """Test HISTCONTROL=erasedups"""

    xession.env["HISTCONTROL"] = "erasedups"
    assert len(hist) == 0

    hist.append({"inp": "ls foo", "rtn": 2})
    hist.append({"inp": "ls foobazz", "rtn": 0})
    hist.append({"inp": "ls foo", "rtn": 0})
    hist.append({"inp": "ls foobazz", "rtn": 0})
    hist.append({"inp": "ls foo", "rtn": 0})
    assert len(hist) == 2
    assert len(hist.inps) == 5

    items = list(hist.items())
    assert "ls foo" == items[-1]["inp"]
    assert "ls foobazz" == items[-2]["inp"]
    assert items[-2]["frequency"] == 2
    assert items[-1]["frequency"] == 3


@pytest.mark.parametrize(
    "index, exp",
    [
        (-1, ("grep from me", "out", 0, (5, 6))),
        (1, ("cat hello kitty", "out", 0, (1, 2))),
        (
            slice(1, 3),
            [("cat hello kitty", "out", 0, (1, 2)), ("abc", "out", 0, (2, 3))],
        ),
    ],
)
def test_history_getitem(index, exp, hist, xession):
    xession.env["HISTCONTROL"] = set()
    xession.env["XONSH_STORE_STDOUT"] = True
    attrs = ("inp", "out", "rtn", "ts")

    for ts, cmd in enumerate(CMDS):  # populate the shell history
        entry = {k: v for k, v in zip(attrs, [cmd, "out", 0, (ts, ts + 1)])}
        hist.append(entry)

    entry = hist[index]
    if isinstance(entry, list):
        assert [(e.cmd, e.out, e.rtn, e.ts) for e in entry] == exp
    else:
        assert (entry.cmd, entry.out, entry.rtn, entry.ts) == exp


def test_hist_clear_cmd(hist, xession, capsys, tmpdir):
    """Verify that the CLI history clear command works."""
    xession.env.update({"XONSH_DATA_DIR": str(tmpdir)})
    xession.history = hist
    xession.env["HISTCONTROL"] = set()

    for ts, cmd in enumerate(CMDS):  # populate the shell history
        hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})
    assert len(xession.history) == 6

    history_main(["clear"])

    out, err = capsys.readouterr()
    assert err.rstrip() == "History cleared"
    assert len(xession.history) == 0


def test_hist_off_cmd(hist, xession, capsys, tmpdir):
    """Verify that the CLI history off command works."""
    xession.env.update({"XONSH_DATA_DIR": str(tmpdir)})
    xession.history = hist
    xession.env["HISTCONTROL"] = set()

    for ts, cmd in enumerate(CMDS):  # populate the shell history
        hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})
    assert len(xession.history) == 6

    history_main(["off"])

    out, err = capsys.readouterr()
    assert err.rstrip() == "History off"
    assert len(xession.history) == 0

    for ts, cmd in enumerate(CMDS):  # attempt to populate the shell history
        hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})

    assert len(xession.history) == 0


def test_hist_on_cmd(hist, xession, capsys, tmpdir):
    """Verify that the CLI history on command works."""
    xession.env.update({"XONSH_DATA_DIR": str(tmpdir)})
    xession.history = hist
    xession.env["HISTCONTROL"] = set()

    for ts, cmd in enumerate(CMDS):  # populate the shell history
        hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})
    assert len(xession.history) == 6

    history_main(["off"])
    history_main(["on"])

    out, err = capsys.readouterr()
    assert err.rstrip().endswith("History on")
    assert len(xession.history) == 0

    for ts, cmd in enumerate(CMDS):  # populate the shell history
        hist.append({"inp": cmd, "rtn": 0, "ts": (ts + 1, ts + 1.5)})

    assert len(xession.history) == 6


def test_hist_store_cwd(hist, xession):
    hist.save_cwd = True
    hist.append({"inp": "# saving with cwd", "rtn": 0, "out": "yes", "cwd": "/tmp"})
    hist.save_cwd = False
    hist.append({"inp": "# saving without cwd", "rtn": 0, "out": "yes", "cwd": "/tmp"})

    cmds = [i for i in hist.all_items()]
    assert cmds[0]["cwd"] == "/tmp"
    assert cmds[1]["cwd"] is None