changeset 5668:a4bb88a1a643

A fix for https://issues.roundup-tracker.org/issue2551034 REST etag ordering. Sort the items before performing the MD5 checksum. This puts the items in the same order every time. I was able to restart the roundup-server and get the same etag value on every restart after this patch. Also the etag calculated using python2 and python3 are now the same. I added a disabled test to try to validate that the etag is always the same value. However there is no way to set the creation and activity dates, so these fields are always different. This means the etag is always different. If I can convince the database back end to use a mocked date.Date.__init__ that returns the same date all the time I can finish the test.
author John Rouillard <rouilj@ieee.org>
date Sat, 23 Mar 2019 00:13:08 -0400
parents 5ad31de777a8
children 1e8f17090a33
files roundup/rest.py test/rest_common.py
diffstat 2 files changed, 28 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/roundup/rest.py	Sat Mar 23 00:02:03 2019 -0400
+++ b/roundup/rest.py	Sat Mar 23 00:13:08 2019 -0400
@@ -132,7 +132,7 @@
     '''
 
     items = node.items(protected=True) # include every item
-    etag = md5(bs2b(repr(items))).hexdigest()
+    etag = md5(bs2b(repr(sorted(items)))).hexdigest()
     logger.debug("object=%s%s; tag=%s; repr=%s", classname, id,
                  etag, repr(node.items(protected=True)))
     return etag
@@ -1336,7 +1336,7 @@
             summary.setdefault(status_name, []).append(issue_object)
             messages.append((num, issue_object))
 
-        messages.sort(reverse=True)
+        sorted(messages, key=lambda tup: tup[0], reverse=True)
 
         result = {
             'created': created,
--- a/test/rest_common.py	Sat Mar 23 00:02:03 2019 -0400
+++ b/test/rest_common.py	Sat Mar 23 00:13:08 2019 -0400
@@ -341,6 +341,32 @@
         #   page_size < 0
         #   page_index < 0
 
+    def notestEtagGeneration(self):
+        ''' Make sure etag generation is stable
+        
+            FIXME need to mock somehow date.Date() when creating
+            the target to be mocked. The differening dates makes
+            this test impossible.
+        '''
+        newuser = self.db.user.create(
+            username='john',
+            password=password.Password('random1'),
+            address='random1@home.org',
+            realname='JohnRandom',
+            roles='User,Admin'
+        )
+
+        node = self.db.user.getnode(self.joeid)
+        etag = calculate_etag(node)
+        items = node.items(protected=True) # include every item
+        print(repr(items))
+        print(etag)
+        self.assertEqual(etag, "6adf97f83acf6453d4a6a4b1070f3754")
+
+        etag = calculate_etag(self.db.issue.getnode("1"))
+        print(etag)
+        self.assertEqual(etag, "6adf97f83acf6453d4a6a4b1070f3754")
+        
     def testEtagProcessing(self):
         '''
         Etags can come from two places:

Roundup Issue Tracker: http://roundup-tracker.org/