1# Test that certain objects conform to well-defined interfaces.
2
3from __future__ import absolute_import, print_function
4
5from mercurial import encoding
6
7encoding.environ[b'HGREALINTERFACES'] = b'1'
8
9import os
10import subprocess
11import sys
12
13# Only run if tests are run in a repo
14if subprocess.call(
15    [sys.executable, '%s/hghave' % os.environ['TESTDIR'], 'test-repo']
16):
17    sys.exit(80)
18
19from mercurial.interfaces import (
20    dirstate as intdirstate,
21    repository,
22)
23from mercurial.thirdparty.zope import interface as zi
24from mercurial.thirdparty.zope.interface import verify as ziverify
25from mercurial import (
26    bundlerepo,
27    dirstate,
28    filelog,
29    httppeer,
30    localrepo,
31    manifest,
32    pycompat,
33    revlog,
34    sshpeer,
35    statichttprepo,
36    ui as uimod,
37    unionrepo,
38    vfs as vfsmod,
39    wireprotoserver,
40    wireprototypes,
41    wireprotov1peer,
42    wireprotov2server,
43)
44
45testdir = os.path.dirname(__file__)
46rootdir = pycompat.fsencode(os.path.normpath(os.path.join(testdir, '..')))
47
48sys.path[0:0] = [testdir]
49import simplestorerepo
50
51del sys.path[0]
52
53
54def checkzobject(o, allowextra=False):
55    """Verify an object with a zope interface."""
56    ifaces = zi.providedBy(o)
57    if not ifaces:
58        print('%r does not provide any zope interfaces' % o)
59        return
60
61    # Run zope.interface's built-in verification routine. This verifies that
62    # everything that is supposed to be present is present.
63    for iface in ifaces:
64        ziverify.verifyObject(iface, o)
65
66    if allowextra:
67        return
68
69    # Now verify that the object provides no extra public attributes that
70    # aren't declared as part of interfaces.
71    allowed = set()
72    for iface in ifaces:
73        allowed |= set(iface.names(all=True))
74
75    public = {a for a in dir(o) if not a.startswith('_')}
76
77    for attr in sorted(public - allowed):
78        print(
79            'public attribute not declared in interfaces: %s.%s'
80            % (o.__class__.__name__, attr)
81        )
82
83
84# Facilitates testing localpeer.
85class dummyrepo(object):
86    def __init__(self):
87        self.ui = uimod.ui()
88        self._wanted_sidedata = set()
89
90    def filtered(self, name):
91        pass
92
93    def _restrictcapabilities(self, caps):
94        pass
95
96
97class dummyopener(object):
98    handlers = []
99
100
101# Facilitates testing sshpeer without requiring a server.
102class badpeer(httppeer.httppeer):
103    def __init__(self):
104        super(badpeer, self).__init__(
105            None, None, None, dummyopener(), None, None
106        )
107        self.badattribute = True
108
109    def badmethod(self):
110        pass
111
112
113class dummypipe(object):
114    def close(self):
115        pass
116
117    @property
118    def closed(self):
119        pass
120
121
122def main():
123    ui = uimod.ui()
124    # Needed so we can open a local repo with obsstore without a warning.
125    ui.setconfig(b'experimental', b'evolution.createmarkers', True)
126
127    checkzobject(badpeer())
128
129    ziverify.verifyClass(repository.ipeerbase, httppeer.httppeer)
130    checkzobject(httppeer.httppeer(None, None, None, dummyopener(), None, None))
131
132    ziverify.verifyClass(repository.ipeerv2, httppeer.httpv2peer)
133    checkzobject(httppeer.httpv2peer(None, b'', b'', None, None, None))
134
135    ziverify.verifyClass(repository.ipeerbase, localrepo.localpeer)
136    checkzobject(localrepo.localpeer(dummyrepo()))
137
138    ziverify.verifyClass(
139        repository.ipeercommandexecutor, localrepo.localcommandexecutor
140    )
141    checkzobject(localrepo.localcommandexecutor(None))
142
143    ziverify.verifyClass(
144        repository.ipeercommandexecutor, wireprotov1peer.peerexecutor
145    )
146    checkzobject(wireprotov1peer.peerexecutor(None))
147
148    ziverify.verifyClass(repository.ipeerbase, sshpeer.sshv1peer)
149    checkzobject(
150        sshpeer.sshv1peer(
151            ui,
152            b'ssh://localhost/foo',
153            b'',
154            dummypipe(),
155            dummypipe(),
156            None,
157            None,
158        )
159    )
160
161    ziverify.verifyClass(repository.ipeerbase, sshpeer.sshv2peer)
162    checkzobject(
163        sshpeer.sshv2peer(
164            ui,
165            b'ssh://localhost/foo',
166            b'',
167            dummypipe(),
168            dummypipe(),
169            None,
170            None,
171        )
172    )
173
174    ziverify.verifyClass(repository.ipeerbase, bundlerepo.bundlepeer)
175    checkzobject(bundlerepo.bundlepeer(dummyrepo()))
176
177    ziverify.verifyClass(repository.ipeerbase, statichttprepo.statichttppeer)
178    checkzobject(statichttprepo.statichttppeer(dummyrepo()))
179
180    ziverify.verifyClass(repository.ipeerbase, unionrepo.unionpeer)
181    checkzobject(unionrepo.unionpeer(dummyrepo()))
182
183    ziverify.verifyClass(
184        repository.ilocalrepositorymain, localrepo.localrepository
185    )
186    ziverify.verifyClass(
187        repository.ilocalrepositoryfilestorage, localrepo.revlogfilestorage
188    )
189    repo = localrepo.makelocalrepository(ui, rootdir)
190    checkzobject(repo)
191
192    ziverify.verifyClass(
193        wireprototypes.baseprotocolhandler, wireprotoserver.sshv1protocolhandler
194    )
195    ziverify.verifyClass(
196        wireprototypes.baseprotocolhandler, wireprotoserver.sshv2protocolhandler
197    )
198    ziverify.verifyClass(
199        wireprototypes.baseprotocolhandler,
200        wireprotoserver.httpv1protocolhandler,
201    )
202    ziverify.verifyClass(
203        wireprototypes.baseprotocolhandler,
204        wireprotov2server.httpv2protocolhandler,
205    )
206
207    sshv1 = wireprotoserver.sshv1protocolhandler(None, None, None)
208    checkzobject(sshv1)
209    sshv2 = wireprotoserver.sshv2protocolhandler(None, None, None)
210    checkzobject(sshv2)
211
212    httpv1 = wireprotoserver.httpv1protocolhandler(None, None, None)
213    checkzobject(httpv1)
214    httpv2 = wireprotov2server.httpv2protocolhandler(None, None)
215    checkzobject(httpv2)
216
217    ziverify.verifyClass(repository.ifilestorage, filelog.filelog)
218    ziverify.verifyClass(repository.imanifestdict, manifest.manifestdict)
219    ziverify.verifyClass(repository.imanifestdict, manifest.treemanifest)
220    ziverify.verifyClass(
221        repository.imanifestrevisionstored, manifest.manifestctx
222    )
223    ziverify.verifyClass(
224        repository.imanifestrevisionwritable, manifest.memmanifestctx
225    )
226    ziverify.verifyClass(
227        repository.imanifestrevisionstored, manifest.treemanifestctx
228    )
229    ziverify.verifyClass(
230        repository.imanifestrevisionwritable, manifest.memtreemanifestctx
231    )
232    ziverify.verifyClass(repository.imanifestlog, manifest.manifestlog)
233    ziverify.verifyClass(repository.imanifeststorage, manifest.manifestrevlog)
234
235    ziverify.verifyClass(
236        repository.irevisiondelta, simplestorerepo.simplestorerevisiondelta
237    )
238    ziverify.verifyClass(repository.ifilestorage, simplestorerepo.filestorage)
239    ziverify.verifyClass(
240        repository.iverifyproblem, simplestorerepo.simplefilestoreproblem
241    )
242
243    ziverify.verifyClass(intdirstate.idirstate, dirstate.dirstate)
244
245    vfs = vfsmod.vfs(b'.')
246    fl = filelog.filelog(vfs, b'dummy.i')
247    checkzobject(fl, allowextra=True)
248
249    # Conforms to imanifestlog.
250    ml = manifest.manifestlog(
251        vfs,
252        repo,
253        manifest.manifestrevlog(repo.nodeconstants, repo.svfs),
254        repo.narrowmatch(),
255    )
256    checkzobject(ml)
257    checkzobject(repo.manifestlog)
258
259    # Conforms to imanifestrevision.
260    mctx = ml[repo[0].manifestnode()]
261    checkzobject(mctx)
262
263    # Conforms to imanifestrevisionwritable.
264    checkzobject(mctx.copy())
265
266    # Conforms to imanifestdict.
267    checkzobject(mctx.read())
268
269    mrl = manifest.manifestrevlog(repo.nodeconstants, vfs)
270    checkzobject(mrl)
271
272    ziverify.verifyClass(repository.irevisiondelta, revlog.revlogrevisiondelta)
273
274    rd = revlog.revlogrevisiondelta(
275        node=b'',
276        p1node=b'',
277        p2node=b'',
278        basenode=b'',
279        linknode=b'',
280        flags=b'',
281        baserevisionsize=None,
282        revision=b'',
283        sidedata=b'',
284        delta=None,
285        protocol_flags=b'',
286    )
287    checkzobject(rd)
288
289    ziverify.verifyClass(repository.iverifyproblem, revlog.revlogproblem)
290    checkzobject(revlog.revlogproblem())
291
292
293main()
294