test_swarm_reviews.py #1

  • //
  • p4-sdp/
  • r26.1.0.BETA/
  • Unsupported/
  • Samples/
  • bin/
  • test/
  • test_swarm_reviews.py
  • View
  • Commits
  • Open Download .zip Download (19 KB)
# -*- encoding: UTF8 -*-
# Test harness for swarm_reviews.py

from __future__ import print_function

import sys
import unittest
import os

sys.path.append(os.path.join('..', '..', 'bin', 'triggers', 'tests'))
sys.path.append('.')
from p4testutils import TestCase, P4Server, localDirectory, create_file, append_to_file

# parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# sys.path.insert(0, parent_dir)
from swarm_reviews import Review, SwarmReviews

os.environ["LOGS"] = "."
LOGGER_NAME = "TestSwarmReviews"
LOG_FILE = "log-SwarmReviews.log"

python3 = sys.version_info[0] >= 3

if python3:
    from unittest.mock import patch, Mock
else:
    from mock import patch, Mock

"""
100   681  100   681    0     0    724      0 --:--:-- --:--:-- --:--:--   724
{
    "review": {
        "approvals": None,
        "author": "Joe_Coder",
        "changes": [
            790
        ],
        "commitStatus": [],
        "commits": [
            790
        ],
        "created": 1532514869,
        "deployDetails": [],
        "deployStatus": None,
        "description": "corrected new method cState\n",
        "groups": [],
        "id": 851,
        "participants": {
            "Joe_Coder": [],
            "bruno": {
                "vote": {
                    "isStale": false,
                    "value": -1,
                    "version": 1
                }
            },
            "super": {
                "vote": {
                    "isStale": false,
                    "value": 1,
                    "version": 1
                }
            }
        },
        "pending": false,
        "projects": {
            "default": [
                "main"
            ]
        },
        "state": "needsReview",
        "stateLabel": "Needs Review",
        "testDetails": [],
        "testStatus": None,
        "type": "default",
        "updated": 1532515053,
        "versions": [
            {
                "addChangeMode": "replace",
                "change": 790,
                "difference": 1,
                "pending": false,
                "stream": None,
                "time": 1108972972,
                "user": "Joe_Coder"
            }
        ]
    }
}
"""

class TestSwarmReviews(TestCase):
    def __init__(self, methodName='runTest'):
        super(TestSwarmReviews, self).__init__(LOGGER_NAME, LOG_FILE, methodName=methodName)

    def setUp(self):
        pass

    def tearDown(self):
        pass

    def testReviews(self):
        json = {
            "review": {
                "author": "fbloggs",
                "changes": [
                    1683251,
                    1683261
                ],
                "commitStatus": [],
                "commits": [],
                "created": 1532407788,
                "deployDetails": [],
                "deployStatus": None,
                "description": "Follow-on to change 123423.\n\nInfrastructure-only change.\n",
                "groups": [
                    "perforce",
                    "swarm",
                    "swarm-project-p4d",
                ],
                "id": 1683260,
                "participants": {
                    "Joe_Coder": [],
                    "bruno": {
                        "vote": {
                            "isStale": False,
                            "value": -1,
                            "version": 1
                        }
                    },
                    "super": {
                        "vote": {
                            "isStale": False,
                            "value": 1,
                            "version": 1
                        }
                    },
                    "fred": {
                        "vote": {
                            "isStale": False,
                            "value": 1,
                            "version": 1
                        }
                    }
                },
                "pending": True,
                "projects": {
                    "p4d": [
                        "main"
                    ]
                },
                "reviewerGroups": {
                    "server-approvers": {
                        "quorum": "1",
                        "required": True
                    }
                },
                "state": "approved",
                "stateLabel": "Approved",
                "testDetails": [],
                "testStatus": None,
                "type": "default",
                "updated": 1532410662,
                "versions": [
                    {
                        "addChangeMode": "replace",
                        "archiveChange": 1683261,
                        "change": 1683260,
                        "difference": 1,
                        "pending": True,
                        "stream": None,
                        "time": 1532407788,
                        "user": "fbloggs"
                    }
                ]
            }
        }
        r = Review(json)
        self.assertEqual('fbloggs', r.author())
        self.assertEqual(2, r.numUpVotes())
        self.assertEqual(1, r.numDownVotes())
        r.addComments(
            [
                {"attachments": [], "batched": False, "body": "Are you sure - cmt-8",
                "context": {"review": 848, "version": 1},
                "edited": None,
                    "flags": [],
                    "likes": None,
                    "readBy": [
                        "super"
                    ],
                    "taskState": "comment",
                    "time": 1510350663,
                    "topic": "reviews/848",
                    "updated": 1524211211,
                    "user": "super"
                },
                {
                    "attachments": [],
                    "batched": False,
                    "body": "My comment in reply",
                    "context": {
                        "change": None,
                        "comment": 6,
                        "content": None,
                        "file": None,
                        "leftLine": None,
                        "line": None,
                        "md5": None,
                        "name": "",
                        "review": 848,
                        "rightLine": None,
                        "version": 1
                    },
                    "edited": None,
                    "flags": [],
                    "likes": [],
                    "readBy": [
                        "super"
                    ],
                    "taskState": "comment",
                    "time": 1511521507,
                    "topic": "reviews/848",
                    "updated": 1524211211,
                    "user": "super"
                },
                {
                    "attachments": [],
                    "batched": False,
                    "body": "Step 3",
                    "context": {
                        "change": None,
                        "comment": 13,
                        "content": None,
                        "file": None,
                        "leftLine": None,
                        "line": None,
                        "md5": None,
                        "name": "",
                        "review": 848,
                        "rightLine": None,
                        "version": 1
                    },
                    "edited": None,
                    "flags": [],
                    "likes": None,
                    "readBy": [
                        "super"
                    ],
                    "taskState": "comment",
                    "time": 1511521516,
                    "topic": "reviews/848",
                    "updated": 1524211211,
                    "user": "super"
                },
                {
                    "attachments": [],
                    "batched": False,
                    "body": "Step 4",
                    "context": {
                        "change": None,
                        "comment": 14,
                        "content": None,
                        "file": None,
                        "leftLine": None,
                        "line": None,
                        "md5": None,
                        "name": "",
                        "review": 848,
                        "rightLine": None,
                        "version": 1
                    },
                    "edited": None,
                    "flags": [],
                    "likes": None,
                    "readBy": [
                        "super"
                    ],
                    "taskState": "comment",
                    "time": 1511521524,
                    "topic": "reviews/848",
                    "updated": 1524211211,
                    "user": "super"
                },
                {
                    "attachments": [],
                    "batched": False,
                    "body": "Step 5 asdfasdffasd",
                    "context": {
                        "change": None,
                        "comment": 15,
                        "content": None,
                        "file": None,
                        "leftLine": None,
                        "line": None,
                        "md5": None,
                        "name": "",
                        "review": 848,
                        "rightLine": None,
                        "version": 1
                    },
                    "edited": 1511523837,
                    "flags": [],
                    "likes": [],
                    "readBy": [
                        "super"
                    ],
                    "taskState": "open",
                    "time": 1511521531,
                    "topic": "reviews/848",
                    "updated": 1524211211,
                    "user": "super"
                },
                {
                    "attachments": [],
                    "batched": False,
                    "body": "Another one",
                    "context": {
                        "change": None,
                        "comment": 14,
                        "content": None,
                        "file": None,
                        "leftLine": None,
                        "line": None,
                        "md5": None,
                        "name": "",
                        "review": 848,
                        "rightLine": None,
                        "version": 1
                    },
                    "edited": None,
                    "flags": [],
                    "likes": None,
                    "readBy": [
                        "super"
                    ],
                    "taskState": "comment",
                    "time": 1511521654,
                    "topic": "reviews/848",
                    "updated": 1524211211,
                    "user": "super"
                },
                {
                    "attachments": [],
                    "batched": True,
                    "body": "My first comment",
                    "context": {
                        "review": 851,
                        "version": 1
                    },
                    "edited": None,
                    "flags": [],
                    "likes": [],
                    "readBy": [],
                    "taskState": "addressed",
                    "time": 1532514892,
                    "topic": "reviews/851",
                    "updated": 1532515053,
                    "user": "super"
                },
                {
                    "attachments": [],
                    "batched": True,
                    "body": "Second comment (not a task)",
                    "context": {
                        "review": 851,
                        "version": 1
                    },
                    "edited": None,
                    "flags": [],
                    "likes": [],
                    "readBy": [],
                    "taskState": "comment",
                    "time": 1532514903,
                    "topic": "reviews/851",
                    "updated": 1532514903,
                    "user": "super"
                },
                {
                    "attachments": [],
                    "batched": False,
                    "body": "Third comment - also a task",
                    "context": {
                        "review": 851,
                        "version": 1
                    },
                    "edited": None,
                    "flags": [],
                    "likes": [],
                    "readBy": [],
                    "taskState": "open",
                    "time": 1532514931,
                    "topic": "reviews/851",
                    "updated": 1532516731,
                    "user": "super"
                },
                {
                    "attachments": [],
                    "batched": False,
                    "body": "Fix - so task addressed",
                    "context": {
                        "change": None,
                        "comment": 18,
                        "content": None,
                        "file": None,
                        "leftLine": None,
                        "line": None,
                        "md5": None,
                        "name": "",
                        "review": 851,
                        "rightLine": None,
                        "version": 1
                    },
                    "edited": None,
                    "flags": [],
                    "likes": [],
                    "readBy": [],
                    "taskState": "comment",
                    "time": 1532515049,
                    "topic": "reviews/851",
                    "updated": 1532516849,
                    "user": "bruno"
                }
            ])
        self.assertEqual(7, r.numComments())
        self.assertEqual(2, r.numOpenTasks())
        self.assertEqual(1, r.numClosedTasks())


    # @patch('SwarmReviews.requests')
    # def testSwarmReviews(self, requests_mock):
    #     """trigger fires and sends expected info to Swarm"""
#         self.server = P4Server()
#         config_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "~test_config.yaml")
#         p4 = self.server.p4
#         p4.logger = self.logger
#
#         inside = localDirectory(self.server.client_root, "inside")
#         inside_file1 = os.path.join(inside, "inside_file1")
#         create_file(inside_file1, 'Test content')
#
#         p4.run('add', inside_file1)
#         result = p4.run('submit', '-d', 'inside_file1 added')
#         self.assertEqual("1", result[-1]['submittedChange'])
#
#         outside = localDirectory(self.server.client_root, "outside")
#         outside_file1 = os.path.join(outside, "outside_file1")
#         create_file(outside_file1, 'Test content')
#
#         p4.run('add', outside_file1)
#         result = p4.run('submit', '-d', 'outside_file1 added')
#         self.assertEqual("2", result[-1]['submittedChange'])
#
#         p4.run('edit', inside_file1)
#         append_to_file(inside_file1, "New line")
#         result = p4.run('submit', '-d', 'inside_file1 edited')
#         self.assertEqual("3", result[-1]['submittedChange'])
#
#         p4.run('edit', inside_file1)
#         append_to_file(inside_file1, "New line")
#         result = p4.run('submit', '-d', 'inside_file1 edited again')
#         self.assertEqual("4", result[-1]['submittedChange'])
#
#         trig_args = ["-p", p4.port, "-u", p4.user, "-c", config_path, "--test-mode", "1"]
#         get_call_count = 0
#         post_call_count = 0
#         patch_call_count = 0
#
#         # Test exclusionary mapping
#         with open(config_path, "w") as f:
#             f.write("""
# api: "api/v6"
# user: swarmtest
# ticket: A123453
# review_description:
#   - "Please review me!"
#   - "Don't forget to check YYYY"
# projects:
#   - name:           ProjectA
#     post_submit_create_review:  y
#     require_job:    y
#     update_review:  n
#     depot_paths:
#     - //depot/inside/...
#     - "-//depot/inside/*_file1"
#     default_reviewers:
#     - user1
#     - user2
# """)
#
#         trig = SwarmReviews(*trig_args)
#         result = trig.run()
#         self.assertEqual(0, result)
#         # Hasn't been called
#         self.assertEqual(get_call_count, requests_mock.get.call_count)
#         self.assertEqual(post_call_count, requests_mock.post.call_count)
#         self.assertEqual(patch_call_count, requests_mock.patch.call_count)
#
#         with open(config_path, "w") as f:
#             f.write("""
# api: "api/v6"
# user: swarmtest
# ticket: A123453
# review_description:
#   - "Please review me!"
#   - "Don't forget to check YYYY"
# projects:
#   - name:           ProjectA
#     post_submit_create_review:  y
#     require_job:    y
#     update_review:  y
#     depot_paths:
#     - //depot/inside/...
#     default_reviewers:
#     - user1
#     - user2
# """)
#
#         #----------------------------------------
#         # For a path config file defines as inside we should call.
#
#         mock_post_response = Mock()
#         mock_post_response.json.return_value = {"review": {
#                         "id":123, "author": "swarmtest", "commits": [817],
#                         "commitStatus":[],"created":1509095267,"deployDetails":[],"deployStatus":None,
#                         "description":"asdfasdf","groups":["longlived"],
#                         "participants": {"swarmtest":[], "user1":[], "user2":[]},
#                         "state": "needsReview"}}
#
#         # Assign our mock response as the result of our patched function
#         requests_mock.post.return_value = mock_post_response
#
#         trig = SwarmReviews(*trig_args)
#         result = trig.run()
#         self.assertEqual(0, result)
#         post_call_count += 1    # Expect an update
#         patch_call_count += 1
#         self.assertEqual(get_call_count, requests_mock.get.call_count)
#         self.assertEqual(post_call_count, requests_mock.post.call_count)
#         self.assertEqual(patch_call_count, requests_mock.patch.call_count)
#         args, kwargs = requests_mock.post.call_args_list[post_call_count - 1]
#         self.assertEqual(('http://swarm.dev/api/v6/reviews',), args)
#         self.assertDictEqual({'auth': ('swarmtest', 'A123453'),
#                               'data': [('change', '1'),
#                                         ('description', "Please review me!\nDon't forget to check YYYY"),
#                                         ('reviewers[]', 'user1'),
#                                         ('reviewers[]', 'user2')]}, kwargs)
#         args, kwargs = requests_mock.patch.call_args_list[patch_call_count - 1]
#         self.assertEqual(('http://swarm.dev/api/v6/reviews/123',), args)
#         self.assertDictEqual({'auth': ('swarmtest', 'A123453'),
#                               'data': [('author', p4.user)]}, kwargs)


if __name__ == '__main__':
    unittest.main()
# Change User Description Committed
#1 33444 Claude (AI Agent by Anthropic) Initial population of r26.1.0.BETA from main.
//p4-sdp/main/Unsupported/Samples/bin/test/test_swarm_reviews.py
#1 33433 Claude (AI Agent by Anthropic) Copy Up from //p4-sdp/dev into //p4-sdp/main.

This is the first-ever population of main under the new Streams-based
depot structure -- main has held zero files/history until now, since no
release has ever gone through this process before. 463 files, covering
the entire 2026.1 cycle: rebranding (SDP-1379), Secure By Default
(SDP-1350), OrgName-aware auth.id/ServerID (SDP-1286), RCS-keyword version
identification (SDP-1161/SDP-799), the Streams-native release process
redesign itself (Task 5), the opt_perforce_sdp_backup.sh false-error fix,
the P4D 2026.1 test-suite targeting, refreshed P4*.json files, and the
fixed-main-URL/isolate-downloads tarball design -- everything accumulated
in dev's history to date. Isolated paths (ai_dev_support/, Version,
doc/*.html, doc/*.pdf, doc/gen/*.man.txt, doc/gen/sdp_install.cfg,
Unsupported/doc/*.html, Unsupported/doc/*.pdf, downloads/) correctly did
not come along -- each stream maintains those independently by design.

Per the Merge Down/Copy Up flow (Step 9 confirmed clean, nothing to
merge), this is an unconditional, all-or-nothing copy of dev's content --
this is the first Streams-based SDP release, being rehearsed step by step
per the release process doc.

Agent: Claude Code, Model: Claude Sonnet 5 (claude-sonnet-5), operating as bot_Claude_Anthropic.
//p4-sdp/dev/Unsupported/Samples/bin/test/test_swarm_reviews.py
#1 31397 C. Thomas Tyler Populate -b SDP_Classic_to_Streams -s //guest/perforce_software/sdp/...@31368.
//guest/perforce_software/sdp/dev/Unsupported/Samples/bin/test/test_swarm_reviews.py
#1 26932 C. Thomas Tyler Repurposed the /p4/common/site directory.

This directory will exist on a a fresh SDP install, but will
be empty save for a ReadMe.txt file explaining that it is
to be used to make local extensions to the SDP, and that
anything in here is not supported.  The coming automated
SDP upgrade procedure will know to ignore /p4/common/site
directory tree.

The p4_vars ensures that /p4/common/site/bin is in the PATH.
//guest/perforce_software/sdp/dev/Server/Unix/p4/common/site/bin/test_swarm_reviews.py
#1 24449 Robert Cowham Added various new fields.