1# -*- coding: utf-8 -*-
2
3import mock
4
5import rosdistro.manifest_provider.github
6import rosdistro.vcs
7
8from rosdistro.manifest_provider.bitbucket import bitbucket_manifest_provider
9from rosdistro.manifest_provider.cache import CachedManifestProvider, sanitize_xml
10from rosdistro.manifest_provider.git import git_manifest_provider, git_source_manifest_provider
11from rosdistro.release_repository_specification import ReleaseRepositorySpecification
12from rosdistro.source_repository_specification import SourceRepositorySpecification
13
14
15def test_bitbucket():
16    assert '</package>' in bitbucket_manifest_provider('indigo', _rospeex_release_repo(), 'rospeex_msgs')
17
18
19def test_cached():
20    class FakeDistributionCache(object):
21        def __init__(self):
22            self.release_package_xmls = {}
23    dc = FakeDistributionCache()
24    cache = CachedManifestProvider(dc, [rosdistro.manifest_provider.github.github_manifest_provider])
25    assert '</package>' in cache('melodic', _genmsg_release_repo(), 'genmsg')
26
27
28def test_git():
29    assert '</package>' in git_manifest_provider('melodic', _genmsg_release_repo(), 'genmsg')
30
31
32def test_git_legacy():
33    rosdistro.vcs.Git._client_version = '1.7.0'
34    assert '</package>' in git_manifest_provider('melodic', _genmsg_release_repo(), 'genmsg')
35    rosdistro.vcs.Git._client_version = None
36
37
38def test_github():
39    assert '</package>' in rosdistro.manifest_provider.github.github_manifest_provider('melodic', _genmsg_release_repo(), 'genmsg')
40
41
42def test_git_source():
43    repo_cache = git_source_manifest_provider(_genmsg_source_repo())
44
45    # This hash corresponds to the 0.5.11 tag.
46    assert repo_cache.ref() == 'a189fc78558e7276df59d2961cfe4f8b4de08a8b'
47
48    package_path, package_xml = repo_cache['genmsg']
49    assert '' == package_path
50    assert '<version>0.5.11</version>' in package_xml
51
52# mock_get_url_contents is used to mock out the '_get_url_contents' method in
53# the rosdistro.manifest_provider.github module.  Instead of going out to github
54# to get data (which can get rate-limited in Travis), it instead pulls a canned
55# example from some local files.
56def mock_get_url_contents(req):
57    import re
58
59    # For python3, look for the 'str' type; for Python 2, the 'unicode' type
60    try:
61        text_type = unicode
62    except NameError:
63        text_type = str
64
65    # The urlopen() function from urllib or urllib2 takes either a string or a
66    # urllib.Request object in; determine the URL in either case.
67    if isinstance(req, text_type):
68        haystack = req
69    else:
70        haystack = req.get_full_url()
71
72    # Now see if the URL ends with 'package.xml'.  If it does, open up the file
73    # that has the canned package.xml data we have for genmsg.  Otherwise,
74    # return the canned JSON tree data that github would have returned.
75    # In both cases, store the file-like object as a module property so that we
76    # can properly close it during 'unmock_urlopen'.
77    if re.search('.*package.xml$', haystack) is not None:
78        fname = 'test/github-genmsg-package.xml'
79    else:
80        fname = 'test/github-tree-data.json'
81
82    with open(fname, 'r') as infp:
83        data = infp.read()
84
85    return data
86
87
88@mock.patch('rosdistro.manifest_provider.github._get_url_contents', mock_get_url_contents)
89def test_github_source():
90    repo_cache = rosdistro.manifest_provider.github.github_source_manifest_provider(_genmsg_source_repo())
91
92    # This hash corresponds to the 0.5.7 tag.
93    assert repo_cache.ref() == '81b66fe5eb00043c43894ddeee07e738d9b9712f'
94
95    package_path, package_xml = repo_cache['genmsg']
96    assert '' == package_path
97    assert '<version>0.5.11</version>' in package_xml
98
99
100def test_git_source_multi():
101    repo_cache = git_source_manifest_provider(_ros_source_repo())
102    assert repo_cache.ref()
103    package_path, package_xml = repo_cache['roslib']
104    assert package_path == 'core/roslib'
105
106
107def test_sanitize():
108    assert '<a>abc</a>' in sanitize_xml('<a>ab<!-- comment -->c</a>')
109    assert '<a><b/><c>ab c</c></a>' in sanitize_xml('<a><b> </b>  <c>  ab  c  </c></a>')
110
111    # This unicode check should be valid on both Python 2 and 3.
112    assert '<a>français</a>' in sanitize_xml('<a> français  </a>')
113
114    # subsequent parse calls will collapse empty tags, therefore sanitize should do the same
115    assert '<a><empty/></a>' in sanitize_xml('<a> <empty> <!-- comment --> </empty> </a>')
116
117
118def _genmsg_release_repo():
119    return ReleaseRepositorySpecification('genmsg', {
120        'url': 'https://github.com/ros-gbp/genmsg-release.git',
121        'tags': {'release': 'release/melodic/{package}/{version}'},
122        'version': '0.5.11-0'
123    })
124
125
126def _genmsg_source_repo():
127    return SourceRepositorySpecification('genmsg', {
128        'url': 'https://github.com/ros/genmsg.git',
129        'version': '0.5.11'
130    })
131
132
133def _ros_source_repo():
134    return SourceRepositorySpecification('ros', {
135        'url': 'https://github.com/ros/ros.git',
136        'version': 'kinetic-devel'
137    })
138
139
140def _rospeex_release_repo():
141    return ReleaseRepositorySpecification('rospeex', {
142        'packages': ['rospeex', 'rospeex_msgs'],
143        'tags': {'release': 'release/indigo/{package}/{version}'},
144        'url': 'https://bitbucket.org/rospeex/rospeex-release.git',
145        'version': '2.14.7-0'
146    })
147