Repository: fedora-infra/bodhi

Issue:
karma not counted correctly
I believe the Karma for the following bodhi update should be +3 rather than +1. Several others (people who understand how karma counting work) agree. Can you please have a look and determine if there is a bug here:

https://bodhi.fedoraproject.org/updates/FEDORA-EPEL-2016-5d93f1948c



Discussion:
I will try to submit patch for it.

Bodhi 2.4.0 reworked how Karma works so that it is dynamically counted rather than denormalized. I was hoping that it would correct this bug, but now the karma is wrong on this update in a different way (It's now +2 and I agree that it should be +3).

I think I know what is happening. The new [karma counting code](https://github.com/fedora-infra/bodhi/blob/2.4.0/bodhi/server/models/models.py#L675-L707) has a protection against a user voting more than once by only considering the user's most recent comment, but it doesn't make sure that the user's most recent comment has a karma value in it:

```
        positive_karma = 0
        negative_karma = 0
        users_counted = set()
        # We want to traverse the comments in reverse order so we only consider the most recent
        # comments from any given user, and only the comments since the most recent karma reset
        # event.
        for comment in reversed(self.comments):
            if (comment.user.name == u'bodhi' and
                    ('New build' in comment.text or 'Removed build' in comment.text)):
                # We only want to consider comments since the most recent karma reset, which happens
                # whenever a build is added or removed from an Update. Since we are traversing the
                # comments in reverse order, once we find one of these comments we can simply exit
                # this loop.
                break
            if not comment.anonymous and comment.user.name not in users_counted:
                # Make sure we only count the last comment this user made
                users_counted.add(comment.user.name)
                if comment.karma > 0:
                    positive_karma += comment.karma
                else:
                    negative_karma += comment.karma

        return positive_karma, negative_karma
```

There should be an ```and comment.karma``` in there so that comments that don't carry karma don't count as the user's vote (which would essentially be a vote for 0). In the example given, @dustymabe's last comment didn't have karma which essentially switched his earlier +1 to a 0.

I'm marking this as an easy fix since I basically just wrote how to fix this in this comment ☺

Resolving patch:
diff --git a/bodhi/server/models.py b/bodhi/server/models.py
--- a/bodhi/server/models.py
+++ b/bodhi/server/models.py
@@ -808,7 +808,7 @@ def _composite_karma(self):
                 # comments in reverse order, once we find one of these comments we can simply exit
                 # this loop.
                 break
-            if not comment.anonymous and comment.user.name not in users_counted:
+            if comment.karma and not comment.anonymous and comment.user.name not in users_counted:
                 # Make sure we only count the last comment this user made
                 users_counted.add(comment.user.name)
                 if comment.karma > 0:


Test patch:
diff --git a/bodhi/tests/server/test_models.py b/bodhi/tests/server/test_models.py
--- a/bodhi/tests/server/test_models.py
+++ b/bodhi/tests/server/test_models.py
@@ -529,6 +529,21 @@ def test__composite_karma_ignores_comments_before_removed_build(self):
 
         eq_(self.obj._composite_karma, (0, -1))
 
+    def test__composite_karma_ignores_comments_without_karma(self):
+        """
+        Assert that _composite_karma ignores comments that don't carry karma.
+
+        See https://github.com/fedora-infra/bodhi/issues/829
+        """
+        self.obj.comment(self.db, u"It ate my ostree", -1, u'dusty')
+        self.obj.comment(self.db, u"i love it push to stable now", 1, u'ididntreallytestitlol')
+        # In bug #829, this comment would have overridden dusty's earlier -1 changing his vote to be
+        # 0.
+        self.obj.comment(self.db, u"plz no don't… my ostreeeeee!", 0, u'dusty')
+
+        # The composite karma should be 1, -1 since dusty's earlier vote should still count.
+        eq_(self.obj._composite_karma, (1, -1))
+
     def test__composite_karma_ignores_old_comments(self):
         """Assert that _composite_karma ignores karma from a user's previous responses."""
         self.obj.comment(self.db, u"I", -1, u'foo')