tests/test-pathencode.py
author Danny Hooper <hooper@google.com>
Fri, 30 Mar 2018 17:01:12 -0700
changeset 37560 41ba336d9f1e
parent 36327 58c1368ab629
child 37880 1b230e19d044
permissions -rw-r--r--
fix: use a portable python script instead of sed in test Differential Revision: https://phab.mercurial-scm.org/D2988
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
17934
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
     1
# This is a randomized test that generates different pathnames every
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
     2
# time it is invoked, and tests the encoding of those pathnames.
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
     3
#
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
     4
# It uses a simple probabilistic model to generate valid pathnames
26098
ce26928cbe41 spelling: behaviour -> behavior
timeless@mozdev.org
parents: 20938
diff changeset
     5
# that have proven likely to expose bugs and divergent behavior in
17934
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
     6
# different encoding implementations.
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
     7
28928
59481bfdb7f3 tests: make test-pathencode use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28918
diff changeset
     8
from __future__ import absolute_import, print_function
28918
72f683260f31 tests: make test-pathencode use print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 26849
diff changeset
     9
28928
59481bfdb7f3 tests: make test-pathencode use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28918
diff changeset
    10
import binascii
17935
9c888b945b65 test-pathencode: make a 2.4-safe import of collections
Bryan O'Sullivan <bryano@fb.com>
parents: 17934
diff changeset
    11
import collections
28928
59481bfdb7f3 tests: make test-pathencode use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28918
diff changeset
    12
import itertools
59481bfdb7f3 tests: make test-pathencode use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28918
diff changeset
    13
import math
59481bfdb7f3 tests: make test-pathencode use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28918
diff changeset
    14
import os
59481bfdb7f3 tests: make test-pathencode use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28918
diff changeset
    15
import random
59481bfdb7f3 tests: make test-pathencode use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28918
diff changeset
    16
import sys
59481bfdb7f3 tests: make test-pathencode use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28918
diff changeset
    17
import time
59481bfdb7f3 tests: make test-pathencode use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28918
diff changeset
    18
from mercurial import (
59481bfdb7f3 tests: make test-pathencode use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28918
diff changeset
    19
    store,
59481bfdb7f3 tests: make test-pathencode use absolute_import
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28918
diff changeset
    20
)
17934
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    21
34224
0f200e2310ca tests: add xrange alias for test-pathencode.py
Augie Fackler <raf@durin42.com>
parents: 28928
diff changeset
    22
try:
0f200e2310ca tests: add xrange alias for test-pathencode.py
Augie Fackler <raf@durin42.com>
parents: 28928
diff changeset
    23
    xrange
0f200e2310ca tests: add xrange alias for test-pathencode.py
Augie Fackler <raf@durin42.com>
parents: 28928
diff changeset
    24
except NameError:
0f200e2310ca tests: add xrange alias for test-pathencode.py
Augie Fackler <raf@durin42.com>
parents: 28928
diff changeset
    25
    xrange = range
0f200e2310ca tests: add xrange alias for test-pathencode.py
Augie Fackler <raf@durin42.com>
parents: 28928
diff changeset
    26
17934
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    27
validchars = set(map(chr, range(0, 256)))
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    28
alphanum = range(ord('A'), ord('Z'))
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    29
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    30
for c in '\0/':
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    31
    validchars.remove(c)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    32
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    33
winreserved = ('aux con prn nul'.split() +
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    34
               ['com%d' % i for i in xrange(1, 10)] +
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    35
               ['lpt%d' % i for i in xrange(1, 10)])
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    36
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    37
def casecombinations(names):
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    38
    '''Build all case-diddled combinations of names.'''
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    39
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    40
    combos = set()
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    41
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    42
    for r in names:
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    43
        for i in xrange(len(r) + 1):
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    44
            for c in itertools.combinations(xrange(len(r)), i):
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    45
                d = r
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    46
                for j in c:
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    47
                    d = ''.join((d[:j], d[j].upper(), d[j + 1:]))
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    48
                combos.add(d)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    49
    return sorted(combos)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    50
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    51
def buildprobtable(fp, cmd='hg manifest tip'):
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    52
    '''Construct and print a table of probabilities for path name
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    53
    components.  The numbers are percentages.'''
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    54
17935
9c888b945b65 test-pathencode: make a 2.4-safe import of collections
Bryan O'Sullivan <bryano@fb.com>
parents: 17934
diff changeset
    55
    counts = collections.defaultdict(lambda: 0)
17934
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    56
    for line in os.popen(cmd).read().splitlines():
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    57
        if line[-2:] in ('.i', '.d'):
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    58
            line = line[:-2]
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    59
        if line.startswith('data/'):
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    60
            line = line[5:]
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    61
        for c in line:
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    62
            counts[c] += 1
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    63
    for c in '\r/\n':
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    64
        counts.pop(c, None)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    65
    t = sum(counts.itervalues()) / 100.0
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    66
    fp.write('probtable = (')
36327
58c1368ab629 py3: use dict.items() instead of dict.iteritems() in tests
Pulkit Goyal <7895pulkit@gmail.com>
parents: 34225
diff changeset
    67
    for i, (k, v) in enumerate(sorted(counts.items(), key=lambda x: x[1],
17934
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    68
                                      reverse=True)):
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    69
        if (i % 5) == 0:
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    70
            fp.write('\n    ')
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    71
        vt = v / t
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    72
        if vt < 0.0005:
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    73
            break
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    74
        fp.write('(%r, %.03f), ' % (k, vt))
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    75
    fp.write('\n    )\n')
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    76
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    77
# A table of character frequencies (as percentages), gleaned by
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    78
# looking at filelog names from a real-world, very large repo.
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    79
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    80
probtable = (
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    81
    ('t', 9.828), ('e', 9.042), ('s', 8.011), ('a', 6.801), ('i', 6.618),
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    82
    ('g', 5.053), ('r', 5.030), ('o', 4.887), ('p', 4.363), ('n', 4.258),
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    83
    ('l', 3.830), ('h', 3.693), ('_', 3.659), ('.', 3.377), ('m', 3.194),
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    84
    ('u', 2.364), ('d', 2.296), ('c', 2.163), ('b', 1.739), ('f', 1.625),
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    85
    ('6', 0.666), ('j', 0.610), ('y', 0.554), ('x', 0.487), ('w', 0.477),
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    86
    ('k', 0.476), ('v', 0.473), ('3', 0.336), ('1', 0.335), ('2', 0.326),
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    87
    ('4', 0.310), ('5', 0.305), ('9', 0.302), ('8', 0.300), ('7', 0.299),
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    88
    ('q', 0.298), ('0', 0.250), ('z', 0.223), ('-', 0.118), ('C', 0.095),
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    89
    ('T', 0.087), ('F', 0.085), ('B', 0.077), ('S', 0.076), ('P', 0.076),
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    90
    ('L', 0.059), ('A', 0.058), ('N', 0.051), ('D', 0.049), ('M', 0.046),
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    91
    ('E', 0.039), ('I', 0.035), ('R', 0.035), ('G', 0.028), ('U', 0.026),
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    92
    ('W', 0.025), ('O', 0.017), ('V', 0.015), ('H', 0.013), ('Q', 0.011),
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    93
    ('J', 0.007), ('K', 0.005), ('+', 0.004), ('X', 0.003), ('Y', 0.001),
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    94
    )
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    95
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    96
for c, _ in probtable:
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    97
    validchars.remove(c)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    98
validchars = list(validchars)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    99
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   100
def pickfrom(rng, table):
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   101
    c = 0
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   102
    r = rng.random() * sum(i[1] for i in table)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   103
    for i, p in table:
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   104
        c += p
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   105
        if c >= r:
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   106
            return i
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   107
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   108
reservedcombos = casecombinations(winreserved)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   109
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   110
# The first component of a name following a slash.
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   111
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   112
firsttable = (
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   113
    (lambda rng: pickfrom(rng, probtable), 90),
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   114
    (lambda rng: rng.choice(validchars), 5),
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   115
    (lambda rng: rng.choice(reservedcombos), 5),
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   116
    )
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   117
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   118
# Components of a name following the first.
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   119
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   120
resttable = firsttable[:-1]
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   121
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   122
# Special suffixes.
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   123
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   124
internalsuffixcombos = casecombinations('.hg .i .d'.split())
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   125
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   126
# The last component of a path, before a slash or at the end of a name.
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   127
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   128
lasttable = resttable + (
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   129
    (lambda rng: '', 95),
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   130
    (lambda rng: rng.choice(internalsuffixcombos), 5),
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   131
    )
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   132
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   133
def makepart(rng, k):
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   134
    '''Construct a part of a pathname, without slashes.'''
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   135
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   136
    p = pickfrom(rng, firsttable)(rng)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   137
    l = len(p)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   138
    ps = [p]
19319
ec17ddecdf64 test-pathencode: randomize length of each path component
Siddharth Agarwal <sid0@fb.com>
parents: 19318
diff changeset
   139
    maxl = rng.randint(1, k)
ec17ddecdf64 test-pathencode: randomize length of each path component
Siddharth Agarwal <sid0@fb.com>
parents: 19318
diff changeset
   140
    while l < maxl:
17934
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   141
        p = pickfrom(rng, resttable)(rng)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   142
        l += len(p)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   143
        ps.append(p)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   144
    ps.append(pickfrom(rng, lasttable)(rng))
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   145
    return ''.join(ps)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   146
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   147
def makepath(rng, j, k):
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   148
    '''Construct a complete pathname.'''
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   149
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   150
    return ('data/' + '/'.join(makepart(rng, k) for _ in xrange(j)) +
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   151
            rng.choice(['.d', '.i']))
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   152
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   153
def genpath(rng, count):
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   154
    '''Generate random pathnames with gradually increasing lengths.'''
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   155
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   156
    mink, maxk = 1, 4096
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   157
    def steps():
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   158
        for i in xrange(count):
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   159
            yield mink + int(round(math.sqrt((maxk - mink) * float(i) / count)))
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   160
    for k in steps():
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   161
        x = rng.randint(1, k)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   162
        y = rng.randint(1, k)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   163
        yield makepath(rng, x, y)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   164
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   165
def runtests(rng, seed, count):
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   166
    nerrs = 0
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   167
    for p in genpath(rng, count):
18435
8c019d2fd7c0 store: switch to C-based hashed path encoding
Bryan O'Sullivan <bryano@fb.com>
parents: 18110
diff changeset
   168
        h = store._pathencode(p)    # uses C implementation, if available
18094
8ceabb34f1cb test-pathencode: compare current pathencoding implementations
Adrian Buehlmann <adrian@cadifra.com>
parents: 17947
diff changeset
   169
        r = store._hybridencode(p, True) # reference implementation in Python
8ceabb34f1cb test-pathencode: compare current pathencoding implementations
Adrian Buehlmann <adrian@cadifra.com>
parents: 17947
diff changeset
   170
        if h != r:
8ceabb34f1cb test-pathencode: compare current pathencoding implementations
Adrian Buehlmann <adrian@cadifra.com>
parents: 17947
diff changeset
   171
            if nerrs == 0:
28918
72f683260f31 tests: make test-pathencode use print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 26849
diff changeset
   172
                print('seed:', hex(seed)[:-1], file=sys.stderr)
72f683260f31 tests: make test-pathencode use print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 26849
diff changeset
   173
            print("\np: '%s'" % p.encode("string_escape"), file=sys.stderr)
72f683260f31 tests: make test-pathencode use print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 26849
diff changeset
   174
            print("h: '%s'" % h.encode("string_escape"), file=sys.stderr)
72f683260f31 tests: make test-pathencode use print_function
Pulkit Goyal <7895pulkit@gmail.com>
parents: 26849
diff changeset
   175
            print("r: '%s'" % r.encode("string_escape"), file=sys.stderr)
18094
8ceabb34f1cb test-pathencode: compare current pathencoding implementations
Adrian Buehlmann <adrian@cadifra.com>
parents: 17947
diff changeset
   176
            nerrs += 1
17934
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   177
    return nerrs
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   178
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   179
def main():
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   180
    import getopt
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   181
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   182
    # Empirically observed to take about a second to run
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   183
    count = 100
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   184
    seed = None
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   185
    opts, args = getopt.getopt(sys.argv[1:], 'c:s:',
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   186
                               ['build', 'count=', 'seed='])
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   187
    for o, a in opts:
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   188
        if o in ('-c', '--count'):
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   189
            count = int(a)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   190
        elif o in ('-s', '--seed'):
34225
d43340bec0f5 tests: use int() instead of long() in test-pathencode.py
Augie Fackler <raf@durin42.com>
parents: 34224
diff changeset
   191
            seed = int(a, base=0) # accepts base 10 or 16 strings
17934
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   192
        elif o == '--build':
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   193
            buildprobtable(sys.stdout,
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   194
                           'find .hg/store/data -type f && '
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   195
                           'cat .hg/store/fncache 2>/dev/null')
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   196
            sys.exit(0)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   197
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   198
    if seed is None:
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   199
        try:
34225
d43340bec0f5 tests: use int() instead of long() in test-pathencode.py
Augie Fackler <raf@durin42.com>
parents: 34224
diff changeset
   200
            seed = int(binascii.hexlify(os.urandom(16)), 16)
17934
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   201
        except AttributeError:
34225
d43340bec0f5 tests: use int() instead of long() in test-pathencode.py
Augie Fackler <raf@durin42.com>
parents: 34224
diff changeset
   202
            seed = int(time.time() * 1000)
17934
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   203
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   204
    rng = random.Random(seed)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   205
    if runtests(rng, seed, count):
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   206
        sys.exit(1)
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   207
17947
f945caa5e963 test-pathencode: more aggressively check for python < 2.6
Bryan O'Sullivan <bryano@fb.com>
parents: 17935
diff changeset
   208
if __name__ == '__main__':
17934
736f1c09f321 tests: add a randomized test for pathencode
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   209
    main()