summaryrefslogtreecommitdiffstats
path: root/extensions/PhabBugz
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/PhabBugz')
-rw-r--r--extensions/PhabBugz/lib/Feed.pm4
-rw-r--r--extensions/PhabBugz/t/basic.t243
-rw-r--r--extensions/PhabBugz/t/feed-daemon-guts.t160
3 files changed, 405 insertions, 2 deletions
diff --git a/extensions/PhabBugz/lib/Feed.pm b/extensions/PhabBugz/lib/Feed.pm
index 8e7290988..1cc73d134 100644
--- a/extensions/PhabBugz/lib/Feed.pm
+++ b/extensions/PhabBugz/lib/Feed.pm
@@ -380,7 +380,7 @@ sub process_revision_change {
# Pre setup before making changes
my $old_user = set_phab_user();
- my $bug = Bugzilla::Bug->new({ id => $revision->bug_id, cache => 1 });
+ my $bug = $revision->bug;
# Check to make sure bug id is valid and author can see it
if ($bug->{error}
@@ -714,7 +714,7 @@ sub process_new_user {
# that are connected to revisions
f11 => 'attachments.filename',
o11 => 'regexp',
- v11 => '^phabricator-D[[:digit:]]+-url[[.period.]]txt$',
+ v11 => '^phabricator-D[[:digit:]]+-url.txt$',
};
my $search = Bugzilla::Search->new( fields => [ 'bug_id' ],
diff --git a/extensions/PhabBugz/t/basic.t b/extensions/PhabBugz/t/basic.t
new file mode 100644
index 000000000..ba2f35e1d
--- /dev/null
+++ b/extensions/PhabBugz/t/basic.t
@@ -0,0 +1,243 @@
+#!/usr/bin/perl
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+use strict;
+use warnings;
+use 5.10.1;
+use lib qw( . lib local/lib/perl5 );
+use Bugzilla;
+
+BEGIN { Bugzilla->extensions };
+
+use Test::More;
+use Test2::Tools::Mock;
+use Data::Dumper;
+use JSON::MaybeXS;
+use Carp;
+use Try::Tiny;
+
+use ok 'Bugzilla::Extension::PhabBugz::Feed';
+use ok 'Bugzilla::Extension::PhabBugz::Util', qw( get_attachment_revisions );
+can_ok('Bugzilla::Extension::PhabBugz::Feed', 'group_query');
+
+our @group_members;
+our @project_members;
+
+
+my $User = mock 'Bugzilla::Extension::PhabBugz::User' => (
+ add_constructor => [
+ 'fake_new' => 'hash',
+ ],
+ override => [
+ 'match' => sub { [ mock() ] },
+ ],
+);
+
+my $Feed = mock 'Bugzilla::Extension::PhabBugz::Feed' => (
+ override => [
+ get_group_members => sub {
+ return [ map { Bugzilla::Extension::PhabBugz::User->fake_new(%$_) } @group_members ];
+ }
+ ]
+);
+
+my $Project = mock 'Bugzilla::Extension::PhabBugz::Project' => (
+ override_constructor => [
+ new_from_query => 'ref_copy',
+ ],
+ override => [
+ 'members' => sub {
+ return [ map { Bugzilla::Extension::PhabBugz::User->fake_new(%$_) } @project_members ];
+ }
+ ]
+);
+
+local Bugzilla->params->{phabricator_enabled} = 1;
+local Bugzilla->params->{phabricator_api_key} = 'FAKE-API-KEY';
+local Bugzilla->params->{phabricator_base_uri} = 'http://fake.fabricator.tld';
+
+my $Bugzilla = mock 'Bugzilla' => (
+ override => [
+ 'dbh' => sub { mock() },
+ 'user' => sub { Bugzilla::User->new({ name => 'phab-bot@bmo.tld' }) },
+ ],
+);
+
+my $BugzillaGroup = mock 'Bugzilla::Group' => (
+ add_constructor => [
+ 'fake_new' => 'hash',
+ ],
+ override => [
+ 'match' => sub { [ Bugzilla::Group->fake_new(id => 1, name => 'firefox-security' ) ] },
+ ],
+);
+
+my $BugzillaUser = mock 'Bugzilla::User' => (
+ add_constructor => [
+ 'fake_new' => 'hash',
+ ],
+ override => [
+ 'new' => sub {
+ my ($class, $hash) = @_;
+ if ($hash->{name} eq 'phab-bot@bmo.tld') {
+ return $class->fake_new( id => 8_675_309, login_name => 'phab-bot@bmo.tld', realname => 'Fake PhabBot' );
+ }
+ else {
+ }
+ },
+ 'match' => sub { [ mock() ] },
+ ],
+);
+
+
+my $feed = Bugzilla::Extension::PhabBugz::Feed->new;
+
+# Same members in both
+do {
+ my $UserAgent = mock 'LWP::UserAgent' => (
+ override => [
+ 'post' => sub {
+ my ($self, $url, $params) = @_;
+ my $data = decode_json($params->{params});
+ is_deeply($data->{transactions}, [], 'no-op');
+ return mock({is_error => 0, content => '{}'});
+ },
+ ],
+ );
+ local @group_members = (
+ { phid => 'foo' },
+ );
+ local @project_members = (
+ { phid => 'foo' },
+ );
+ $feed->group_query;
+};
+
+# Project has members not in group
+do {
+ my $UserAgent = mock 'LWP::UserAgent' => (
+ override => [
+ 'post' => sub {
+ my ($self, $url, $params) = @_;
+ my $data = decode_json($params->{params});
+ my $expected = [ { type => 'members.remove', value => ['foo'] } ];
+ is_deeply($data->{transactions}, $expected, 'remove foo');
+ return mock({is_error => 0, content => '{}'});
+ },
+ ]
+ );
+ local @group_members = ();
+ local @project_members = (
+ { phid => 'foo' },
+ );
+ $feed->group_query;
+};
+
+# Group has members not in project
+do {
+ my $UserAgent = mock 'LWP::UserAgent' => (
+ override => [
+ 'post' => sub {
+ my ($self, $url, $params) = @_;
+ my $data = decode_json($params->{params});
+ my $expected = [ { type => 'members.add', value => ['foo'] } ];
+ is_deeply($data->{transactions}, $expected, 'add foo');
+ return mock({is_error => 0, content => '{}'});
+ },
+ ]
+ );
+ local @group_members = (
+ { phid => 'foo' },
+ );
+ local @project_members = (
+ );
+ $feed->group_query;
+};
+
+do {
+ my $Revision = mock 'Bugzilla::Extension::PhabBugz::Revision' => (
+ override => [
+ 'update' => sub { 1 },
+ ],
+ );
+ my $UserAgent = mock 'LWP::UserAgent' => (
+ override => [
+ 'post' => sub {
+ my ($self, $url, $params) = @_;
+ if ($url =~ /differential\.revision\.search/) {
+ my $content = <<JSON;
+{
+ "error_info": null,
+ "error_code": null,
+ "result": {
+ "data": [
+ {
+ "id": 9999,
+ "type": "DREV",
+ "phid": "PHID-DREV-uozm3ggfp7e7uoqegmc3",
+ "fields": {
+ "title": "Added .arcconfig",
+ "summary": "Added .arcconfig",
+ "authorPHID": "PHID-USER-4wigy3sh5fc5t74vapwm",
+ "dateCreated": 1507666113,
+ "dateModified": 1508514027,
+ "policy": {
+ "view": "public",
+ "edit": "admin"
+ },
+ "bugzilla.bug-id": "23",
+ "status": {
+ "value": "needs-review",
+ "name": "Needs Review",
+ "closed": false,
+ "color.ansi": "magenta"
+ }
+ },
+ "attachments": {
+ "reviewers": {
+ "reviewers": []
+ },
+ "subscribers": {
+ "subscriberPHIDs": [],
+ "subscriberCount": 0,
+ "viewerIsSubscribed": true
+ },
+ "projects": {
+ "projectPHIDs": []
+ }
+ }
+ }
+ ]
+ }
+}
+JSON
+ return mock { is_error => 0, content => $content };
+ }
+ else {
+ return mock { is_error => 1, message => "bad request" };
+ }
+ },
+ ],
+ );
+ my $bug = mock {
+ bug_id => 23,
+ attachments => [
+ mock {
+ contenttype => 'text/x-phabricator-request',
+ filename => 'phabricator-D9999-url.txt',
+ },
+ ]
+ };
+ my $revisions = get_attachment_revisions($bug);
+ is(ref($revisions), 'ARRAY', 'it is an array ref');
+ isa_ok($revisions->[0], 'Bugzilla::Extension::PhabBugz::Revision');
+ is($revisions->[0]->bug_id, 23, 'Bugzila ID is 23');
+ ok( try { $revisions->[0]->update }, 'update revision');
+
+};
+
+done_testing; \ No newline at end of file
diff --git a/extensions/PhabBugz/t/feed-daemon-guts.t b/extensions/PhabBugz/t/feed-daemon-guts.t
new file mode 100644
index 000000000..376af18e4
--- /dev/null
+++ b/extensions/PhabBugz/t/feed-daemon-guts.t
@@ -0,0 +1,160 @@
+#!/usr/bin/perl
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+use strict;
+use warnings;
+use 5.10.1;
+use lib qw( . lib local/lib/perl5 );
+BEGIN { $ENV{LOG4PERL_CONFIG_FILE} = 'log4perl-t.conf' }
+use Bugzilla::Test::MockDB;
+use Bugzilla::Test::MockParams;
+use Bugzilla::Test::Util qw(create_user);
+use Test::More;
+use Test2::Tools::Mock;
+use Try::Tiny;
+use JSON::MaybeXS;
+use Bugzilla::Constants;
+use URI;
+use File::Basename;
+use Digest::SHA qw(sha1_hex);
+
+use ok 'Bugzilla::Extension::PhabBugz::Feed';
+use ok 'Bugzilla::Extension::PhabBugz::Constants', 'PHAB_AUTOMATION_USER';
+use ok 'Bugzilla::Config', 'SetParam';
+can_ok('Bugzilla::Extension::PhabBugz::Feed', qw( group_query feed_query user_query ));
+
+Bugzilla->error_mode(ERROR_MODE_TEST);
+
+my $phab_bot = create_user(PHAB_AUTOMATION_USER, '*');
+
+my $UserAgent = mock 'LWP::UserAgent' => ();
+
+{
+ SetParam('phabricator_enabled', 0);
+ my $feed = Bugzilla::Extension::PhabBugz::Feed->new;
+ my $Feed = mock 'Bugzilla::Extension::PhabBugz::Feed' => (
+ override => [
+ get_last_id => sub { die "get_last_id" },
+ ],
+ );
+
+ foreach my $method (qw( feed_query user_query group_query )) {
+ try {
+ $feed->$method;
+ pass "disabling the phabricator sync: $method";
+ }
+ catch {
+ fail "disabling the phabricator sync: $method";
+ }
+ }
+}
+
+my @bad_response = (
+ ['http error', mock({ is_error => 1, message => 'some http error' }) ],
+ ['invalid json', mock({ is_error => 0, content => '<xml>foo</xml>' })],
+ ['json containing error code', mock({ is_error => 0, content => encode_json({error_code => 1234 }) })],
+);
+
+SetParam(phabricator_enabled => 1);
+SetParam(phabricator_api_key => 'FAKE-API-KEY');
+SetParam(phabricator_base_uri => 'http://fake.fabricator.tld/');
+
+foreach my $bad_response (@bad_response) {
+ my $feed = Bugzilla::Extension::PhabBugz::Feed->new;
+ $UserAgent->override(
+ post => sub {
+ my ( $self, $url, $params ) = @_;
+ return $bad_response->[1];
+ }
+ );
+
+ foreach my $method (qw( feed_query user_query group_query )) {
+ try {
+ # This is a hack to get reasonable exception objects.
+ local $Bugzilla::Template::is_processing = 1;
+ $feed->$method;
+ fail "$method - $bad_response->[0]";
+ }
+ catch {
+ is( $_->type, 'bugzilla.code.phabricator_api_error', "$method - $bad_response->[0]" );
+ };
+ }
+ $UserAgent->reset('post');
+}
+
+my $feed = Bugzilla::Extension::PhabBugz::Feed->new;
+my $json = JSON::MaybeXS->new( canonical => 1, pretty => 1 );
+my $dylan = create_user( 'dylan@mozilla.com', '*', realname => 'Dylan Hardison :dylan' );
+my $evildylan = create_user( 'dylan@gmail.com', '*', realname => 'Evil Dylan :dylan' );
+my $myk = create_user( 'myk@mozilla.com', '*', realname => 'Myk Melez :myk' );
+
+my $phab_bot_phid = next_phid('PHID-USER');
+
+done_testing;
+
+sub user_search {
+ my (%conf) = @_;
+
+ return {
+ error_info => undef,
+ error_code => undef,
+ result => {
+ cursor => {
+ after => $conf{after},
+ order => undef,
+ limit => 100,
+ before => undef
+ },
+ query => {
+ queryKey => undef
+ },
+ maps => {},
+ data => [
+ map {
+ +{
+ attachments => {
+ $_->{bmo_id}
+ ? ( "external-accounts" => {
+ "external-accounts" => [
+ {
+ type => 'bmo',
+ id => $_->{bmo_id},
+ }
+ ]
+ }
+ )
+ : (),
+ },
+ fields => {
+ roles => [ "verified", "approved", "activated" ],
+ realName => $_->{realname},
+ dateModified => time,
+ policy => {
+ view => "public",
+ edit => "no-one"
+ },
+ dateCreated => time,
+ username => $_->{username},
+ },
+ phid => next_phid("PHID-USER"),
+ type => "USER",
+ id => $_->{phab_id},
+ },
+ } @{ $conf{users} },
+ ]
+ }
+ };
+
+}
+
+sub next_phid {
+ my ($prefix) = @_;
+ state $number = 'a' x 20;
+ return $prefix . '-' . ($number++);
+}
+
+