Skip to content

Commit

Permalink
Add sorting of ApiRoute, guaranteeing stable file output. (#260)
Browse files Browse the repository at this point in the history
* Add sorting of ApiRoute, guaranteeing stable file output.

Co-authored-by: Jeff Forbes <jforbes@dropbox.com>
  • Loading branch information
yanks and Jeff Forbes committed Jan 7, 2022
1 parent 2996b3c commit 32b0c0f
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 0 deletions.
5 changes: 5 additions & 0 deletions stone/frontend/ir_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -1704,6 +1704,11 @@ def _filter_namespaces_by_route_whitelist(self):
namespace.routes = []
namespace.route_by_name = {}
namespace.routes_by_name = {}

# We need a stable sort in order to keep the resultant output
# the same across runs.
routes.sort()

for route in routes:
namespace.add_route(route)

Expand Down
25 changes: 25 additions & 0 deletions stone/ir/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,31 @@ def name_with_version(self):
def __repr__(self):
return 'ApiRoute({})'.format(self.name_with_version())

def _compare(self, lhs, rhs):
if not isinstance(lhs, ApiRoute):
raise TypeError("Expected ApiRoute for object: {}".format(lhs))
if not isinstance(rhs, ApiRoute):
raise TypeError("Expected ApiRoute for object: {}".format(rhs))

if lhs.name < rhs.name or lhs.version < rhs.version:
return -1
elif lhs.name > rhs.name or lhs.version > rhs.version:
return 1
else:
return 0

def __lt__(self, other):
return self._compare(self, other) < 0
def __gt__(self, other):
return self._compare(self, other) > 0
def __eq__(self, other):
return self._compare(self, other) == 0
def __le__(self, other):
return self._compare(self, other) <= 0
def __ge__(self, other):
return self._compare(self, other) >= 0
def __ne__(self, other):
return self._compare(self, other) != 0

class DeprecationInfo(object):

Expand Down
48 changes: 48 additions & 0 deletions test/test_stone_route_whitelist.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,54 @@ def test_simple(self):
self._compare_namespace_names(api, ['test'])
self._compare_datatype_names(api.namespaces['test'], ['TestArg2', 'TestResult2'])

def test_stable_ordering(self):
"""
Tests that route generation returns the same route order on generation.
"""
text = textwrap.dedent("""\
namespace test
struct TestArg
f String
"test doc"
example default
f = "asdf"
struct TestResult
f String
"test doc"
example default
f = "asdf"
route TestRoute (TestArg, TestResult, Void)
"test doc"
route OtherRoute (Void, Void, Void)
"Additional Route"
""")

route_whitelist = ["OtherRoute", "TestRoute"]

for x in range(2, 100):
text += textwrap.dedent("""\
route TestRoute:{} (TestArg, TestResult, Void)
"test doc"
""".format(x))
route_whitelist.append("TestRoute:{}".format(x))

route_whitelist_filter = {
"route_whitelist": {"test": route_whitelist},
"datatype_whitelist": {}
}

api = specs_to_ir([('test.stone', text)], route_whitelist_filter=route_whitelist_filter)
routes = api.namespaces['test'].routes
self.assertEqual(len(routes), 100)
self.assertEqual(routes[0].name, "OtherRoute")

for x in range(1, 100):
self.assertEqual(routes[x].name, "TestRoute")
self.assertEqual(routes[x].version, x)

def test_star(self):
"""
Tests that inputs with "*" work as expected.
Expand Down

0 comments on commit 32b0c0f

Please sign in to comment.