tests/test-simplekeyvaluefile.py
author Kostia Balytskyi <ikostia@fb.com>
Fri, 10 Mar 2017 14:33:42 -0800
changeset 31553 56acc4250900
child 31585 c6921568cd20
permissions -rw-r--r--
scmutil: add a simple key-value file helper The purpose of the added class is to serve purposes like save files of shelve or state files of shelve, rebase and histedit. Keys of these files can be alphanumeric and start with letters, while values must not contain newlines. In light of Mercurial's reluctancy to use Python's json module, this tries to provide a reasonable alternative for a non-nested named data. Comparing to current approach of storing state in plain text files, where semantic meaning of lines of text is only determined by their oreder, simple key-value file allows for reordering lines and thus helps handle optional values. Initial use-case I see for this is obs-shelve's shelve files. Later we can possibly migrate state files to this approach. The test is in a new file beause I did not figure out where to put it within existing test suite. If you give me a better idea, I will gladly follow it.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
31553
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
     1
from __future__ import absolute_import
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
     2
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
     3
import unittest
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
     4
import silenttestrunner
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
     5
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
     6
from mercurial import (
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
     7
    error,
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
     8
    scmutil,
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
     9
)
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    10
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    11
class mockfile(object):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    12
    def __init__(self, name, fs):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    13
        self.name = name
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    14
        self.fs = fs
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    15
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    16
    def __enter__(self):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    17
        return self
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    18
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    19
    def __exit__(self, *args, **kwargs):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    20
        pass
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    21
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    22
    def write(self, text):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    23
        self.fs.contents[self.name] = text
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    24
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    25
    def read(self):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    26
        return self.fs.contents[self.name]
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    27
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    28
class mockvfs(object):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    29
    def __init__(self):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    30
        self.contents = {}
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    31
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    32
    def read(self, path):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    33
        return mockfile(path, self).read()
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    34
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    35
    def readlines(self, path):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    36
        return mockfile(path, self).read().split('\n')
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    37
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    38
    def __call__(self, path, mode, atomictemp):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    39
        return mockfile(path, self)
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    40
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    41
class testsimplekeyvaluefile(unittest.TestCase):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    42
    def setUp(self):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    43
        self.vfs = mockvfs()
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    44
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    45
    def testbasicwriting(self):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    46
        d = {'key1': 'value1', 'Key2': 'value2'}
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    47
        scmutil.simplekeyvaluefile(self.vfs, 'kvfile').write(d)
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    48
        self.assertEqual(sorted(self.vfs.read('kvfile').split('\n')),
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    49
                         ['', 'Key2=value2', 'key1=value1'])
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    50
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    51
    def testinvalidkeys(self):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    52
        d = {'0key1': 'value1', 'Key2': 'value2'}
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    53
        with self.assertRaisesRegexp(error.ProgrammingError,
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    54
                                     "keys must start with a letter.*"):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    55
            scmutil.simplekeyvaluefile(self.vfs, 'kvfile').write(d)
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    56
        d = {'key1@': 'value1', 'Key2': 'value2'}
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    57
        with self.assertRaisesRegexp(error.ProgrammingError, "invalid key.*"):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    58
            scmutil.simplekeyvaluefile(self.vfs, 'kvfile').write(d)
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    59
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    60
    def testinvalidvalues(self):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    61
        d = {'key1': 'value1', 'Key2': 'value2\n'}
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    62
        with self.assertRaisesRegexp(error.ProgrammingError, "invalid val.*"):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    63
            scmutil.simplekeyvaluefile(self.vfs, 'kvfile').write(d)
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    64
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    65
    def testcorruptedfile(self):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    66
        self.vfs.contents['badfile'] = 'ababagalamaga\n'
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    67
        with self.assertRaisesRegexp(error.CorruptedState,
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    68
                                     "dictionary.*element.*"):
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    69
            scmutil.simplekeyvaluefile(self.vfs, 'badfile').read()
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    70
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    71
if __name__ == "__main__":
56acc4250900 scmutil: add a simple key-value file helper
Kostia Balytskyi <ikostia@fb.com>
parents:
diff changeset
    72
    silenttestrunner.main(__name__)