summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.circleci/checksetup_answers.txt4
-rw-r--r--.circleci/config.yml37
-rw-r--r--Bugzilla/Test/Util.pm32
-rwxr-xr-xscripts/entrypoint.pl22
-rwxr-xr-xscripts/generate_bmo_data.pl4
-rw-r--r--t/bmo/passwords.t260
6 files changed, 351 insertions, 8 deletions
diff --git a/.circleci/checksetup_answers.txt b/.circleci/checksetup_answers.txt
index 80a1d40d2..bcdefa38e 100644
--- a/.circleci/checksetup_answers.txt
+++ b/.circleci/checksetup_answers.txt
@@ -1,11 +1,13 @@
$answer{'ADMIN_EMAIL'} = 'admin@mozilla.bugs';
$answer{'ADMIN_OK'} = 'Y';
-$answer{'ADMIN_PASSWORD'} = 'password';
+$answer{'ADMIN_PASSWORD'} = 'passWord1234!';
$answer{'ADMIN_REALNAME'} = 'QA Admin';
$answer{'NO_PAUSE'} = 1;
$answer{'bugzilla_version'} = '1';
$answer{'create_htaccess'} = '1';
$answer{'cvsbin'} = '/usr/bin/cvs';
+$answer{'password_complexity'} = 'bmo';
$answer{'diffpath'} = '/usr/bin';
$answer{'interdiffbin'} = '/usr/bin/interdiff';
$answer{'urlbase'} = 'http://<<HOSTNAME>>:8000/';
+$answer{'mail_delivery_method'} = 'Test';
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 619f1cb11..cd2ec0e10 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -120,13 +120,48 @@ jobs:
- store_artifacts:
path: /app/artifacts
+ test_bmo:
+ parallelism: 4
+ working_directory: /app
+ docker:
+ - <<: *bmo_slim_image
+ environment:
+ <<: *bmo_env
+ BZ_QA_ANSWERS_FILE: /app/.circleci/checksetup_answers.txt
+ TWD_HOST: localhost
+ TWD_PORT: 4444
+ TWD_BROWSER: firefox
+ - <<: *mysql_image
+ environment: *mysql_env
+ - image: memcached:latest
+ - image: selenium/standalone-firefox:2.53.1
+ steps:
+ - checkout
+ - run: |
+ mv /opt/bmo/local /app/local
+ perl checksetup.pl --no-database --default-localconfig
+ perl -MSys::Hostname -i -pE 's/<<HOSTNAME>>/hostname()/ges' $BZ_QA_ANSWERS_FILE
+ rm -f /app/localconfig
+ /app/scripts/entrypoint.pl load_test_data
+ mkdir artifacts
+ - run: |
+ BZ_BASE_URL="http://$(hostname):$PORT"
+ export BZ_BASE_URL
+ rm -f /app/localconfig
+ /app/scripts/entrypoint.pl test_bmo -q -f t/bmo/*.t
+
+
+
workflows:
version: 2
tests:
jobs:
+ - test_bmo
- test_sanity
- test_webservices
- - test_selenium
+ - test_selenium:
+ requires:
+ - test_bmo
- build:
requires:
- test_sanity
diff --git a/Bugzilla/Test/Util.pm b/Bugzilla/Test/Util.pm
new file mode 100644
index 000000000..4c9981e52
--- /dev/null
+++ b/Bugzilla/Test/Util.pm
@@ -0,0 +1,32 @@
+# 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.
+
+package Bugzilla::Test::Util;
+
+use 5.10.1;
+use strict;
+use warnings;
+
+use base qw(Exporter);
+our @EXPORT = qw(create_user);
+
+use Bugzilla::User;
+
+sub create_user {
+ my ($login, $password, %extra) = @_;
+ require Bugzilla;
+ return Bugzilla::User->create({
+ login_name => $login,
+ cryptpassword => $password,
+ disabledtext => "",
+ disable_mail => 0,
+ extern_id => 0,
+ %extra,
+ });
+}
+
+1;
diff --git a/scripts/entrypoint.pl b/scripts/entrypoint.pl
index 2d1ef8fe9..c39551131 100755
--- a/scripts/entrypoint.pl
+++ b/scripts/entrypoint.pl
@@ -3,16 +3,18 @@ use 5.10.1;
use strict;
use warnings;
use lib qw(/app /app/local/lib/perl5);
+
use Bugzilla::Install::Localconfig ();
use Bugzilla::Install::Util qw(install_string);
+use Bugzilla::Test::Util qw(create_user);
use DBI;
use Data::Dumper;
use English qw($EUID);
use File::Copy::Recursive qw(dircopy);
use Getopt::Long qw(:config gnu_getopt);
use LWP::Simple qw(get);
-use User::pwent;
use POSIX qw(WEXITSTATUS setsid);
+use User::pwent;
use IO::Async::Loop;
use IO::Async::Process;
@@ -53,7 +55,7 @@ sub cmd_load_test_data {
run( 'perl', 'generate_test_data.pl' );
}
else {
- run( 'perl', 'scripts/generate_bmo_data.pl' );
+ run( 'perl', 'scripts/generate_bmo_data.pl', '--param' => 'use_mailer_queue=0' );
}
}
@@ -76,6 +78,8 @@ sub cmd_test_webservices {
my $conf = require $ENV{BZ_QA_CONF_FILE};
check_data_dir();
+ wait_for_db();
+
my @httpd_cmd = ( '/usr/sbin/httpd', '-DFOREGROUND', '-f', '/app/httpd/httpd.conf' );
if ($ENV{BZ_QA_LEGACY_MODE}) {
copy_qa_extension();
@@ -98,6 +102,7 @@ sub cmd_test_selenium {
my $conf = require $ENV{BZ_QA_CONF_FILE};
check_data_dir();
+ wait_for_db();
my @httpd_cmd = ( '/usr/sbin/httpd', '-DFOREGROUND', '-f', '/app/httpd/httpd.conf' );
if ($ENV{BZ_QA_LEGACY_MODE}) {
copy_qa_extension();
@@ -121,6 +126,16 @@ sub cmd_prove { run( "prove", "-I/app", "-I/app/local/lib/perl5", @_ ); }
sub cmd_version { run( 'cat', '/app/version.json' ); }
sub cmd_test_bmo {
+ check_data_dir();
+ wait_for_db();
+
+ $ENV{BZ_TEST_NEWBIE} = 'newbie@mozilla.example';
+ $ENV{BZ_TEST_NEWBIE_PASS} = 'captain.space.bagel.ROBOT!';
+ create_user($ENV{BZ_TEST_NEWBIE}, $ENV{BZ_TEST_NEWBIE_PASS}, realname => "Newbie User");
+
+ $ENV{BZ_TEST_NEWBIE2} = 'newbie2@mozilla.example';
+ $ENV{BZ_TEST_NEWBIE2_PASS} = 'captain.space.pants.time.lord';
+
prove_with_httpd(
httpd_url => $ENV{BZ_BASE_URL},
httpd_cmd => [ '/usr/sbin/httpd', '-f', '/app/httpd/httpd.conf', '-DFOREGROUND' ],
@@ -131,9 +146,6 @@ sub cmd_test_bmo {
sub prove_with_httpd {
my (%param) = @_;
- check_data_dir();
- wait_for_db();
-
unless (-d "/app/logs") {
mkdir("/app/logs") or die "unable to mkdir(/app/logs): $!\n";
}
diff --git a/scripts/generate_bmo_data.pl b/scripts/generate_bmo_data.pl
index 788227443..b2df7ddba 100755
--- a/scripts/generate_bmo_data.pl
+++ b/scripts/generate_bmo_data.pl
@@ -63,7 +63,8 @@ my %user_prefs = (
zoom_textareas => 'off',
);
-GetOptions('user-pref=s%' => \%user_prefs);
+my %opt_param;
+GetOptions('user-pref=s%' => \%user_prefs, 'param=s' => \%opt_param);
my $admin_email = shift || 'admin@mozilla.bugs';
Bugzilla->set_user(Bugzilla::User->check({ name => $admin_email }));
@@ -496,6 +497,7 @@ my %set_params = (
use_mailer_queue => 1,
user_info_class => 'GitHubAuth,CGI',
user_verify_class => 'GitHubAuth,DB',
+ %opt_param,
);
my $params_modified;
diff --git a/t/bmo/passwords.t b/t/bmo/passwords.t
new file mode 100644
index 000000000..d10eddff7
--- /dev/null
+++ b/t/bmo/passwords.t
@@ -0,0 +1,260 @@
+#!/usr/bin/env perl
+use 5.10.1;
+use strict;
+use warnings;
+use autodie;
+use constant DRIVER => 'Test::Selenium::Remote::Driver';
+
+use Test::More 1.302;
+#use constant DRIVER => 'Test::Selenium::Chrome';
+BEGIN { plan skip_all => "these tests only run in CI" unless $ENV{CI} && $ENV{CIRCLE_JOB} eq 'test_bmo' };
+
+use ok DRIVER;
+
+my $ADMIN_LOGIN = $ENV{BZ_TEST_ADMIN} // 'admin@mozilla.bugs';
+my $ADMIN_PW_OLD = $ENV{BZ_TEST_ADMIN_PASS} // 'passWord1234!';
+my $ADMIN_PW_NEW = $ENV{BZ_TEST_ADMIN_NEWPASS} // 'she7Ka8t';
+
+my @require_env = qw(
+ BZ_BASE_URL
+ BZ_TEST_NEWBIE
+ BZ_TEST_NEWBIE_PASS
+);
+
+if (DRIVER =~ /Remote/) {
+ push @require_env, qw( TWD_HOST TWD_PORT );
+}
+my @missing_env = grep { ! exists $ENV{$_} } @require_env;
+BAIL_OUT("Missing env: @missing_env") if @missing_env;
+
+eval {
+ my $sel = DRIVER->new(base_url => $ENV{BZ_BASE_URL});
+ $sel->set_implicit_wait_timeout(600);
+
+ login_ok($sel, $ADMIN_LOGIN, $ADMIN_PW_OLD);
+
+ change_password($sel, $ADMIN_PW_OLD, 'newpassword', 'newpassword2');
+ $sel->title_is("Passwords Don't Match");
+ $sel->body_text_contains('The two passwords you entered did not match.');
+
+ change_password($sel, $ADMIN_PW_OLD . "x", "newpassword2", "newpassword2");
+ $sel->title_is("Incorrect Old Password");
+
+ change_password($sel, $ADMIN_PW_OLD, "password", "password");
+ $sel->title_is("Password Fails Requirements");
+
+ change_password($sel, $ADMIN_PW_OLD, $ADMIN_PW_NEW, $ADMIN_PW_NEW);
+ $sel->title_is("User Preferences");
+ logout_ok($sel);
+
+ login_ok($sel, $ADMIN_LOGIN, $ADMIN_PW_NEW);
+
+ # we don't protect against password re-use
+ change_password($sel, $ADMIN_PW_NEW, $ADMIN_PW_OLD, $ADMIN_PW_OLD);
+ $sel->title_is("User Preferences");
+ logout_ok($sel);
+
+ login_ok($sel, $ENV{BZ_TEST_NEWBIE}, $ENV{BZ_TEST_NEWBIE_PASS});
+
+ $sel->get_ok("/editusers.cgi");
+ $sel->title_is("Authorization Required");
+ logout_ok($sel);
+
+ login_ok($sel, $ADMIN_LOGIN, $ADMIN_PW_OLD);
+
+ toggle_require_password_change($sel, $ENV{BZ_TEST_NEWBIE});
+ logout_ok($sel);
+
+ login($sel, $ENV{BZ_TEST_NEWBIE}, $ENV{BZ_TEST_NEWBIE_PASS});
+ $sel->title_is('Password change required');
+ click_and_type($sel, "old_password", $ENV{BZ_TEST_NEWBIE_PASS});
+ click_and_type($sel, "new_password1", "password");
+ click_and_type($sel, "new_password2", "password");
+ submit($sel, '//input[@id="submit"]');
+ $sel->title_is('Password Fails Requirements');
+
+ $sel->go_back_ok();
+ $sel->title_is('Password change required');
+ click_and_type($sel, "old_password", $ENV{BZ_TEST_NEWBIE_PASS});
+ click_and_type($sel, "new_password1", "!!" . $ENV{BZ_TEST_NEWBIE_PASS});
+ click_and_type($sel, "new_password2", "!!" . $ENV{BZ_TEST_NEWBIE_PASS});
+ submit($sel, '//input[@id="submit"]');
+ $sel->title_is('Password Changed');
+ change_password(
+ $sel,
+ "!!" . $ENV{BZ_TEST_NEWBIE_PASS},
+ $ENV{BZ_TEST_NEWBIE_PASS},
+ $ENV{BZ_TEST_NEWBIE_PASS}
+ );
+ $sel->title_is("User Preferences");
+
+ $sel->get_ok("/userprefs.cgi?tab=account");
+ $sel->title_is("User Preferences");
+ click_link($sel, "I forgot my password");
+ $sel->body_text_contains(
+ ["A token for changing your password has been emailed to you.",
+ "Follow the instructions in that email to change your password."],
+ );
+ my $token = get_token();
+ ok($token, "got a token from resetting password");
+ $sel->get_ok("/token.cgi?t=$token&a=cfmpw");
+ $sel->title_is('Change Password');
+ click_and_type($sel, "password", "nopandas");
+ click_and_type($sel, "matchpassword", "nopandas");
+ submit($sel, '//input[@id="update"]');
+ $sel->title_is('Password Fails Requirements');
+ $sel->go_back_ok();
+ $sel->title_is('Change Password');
+ click_and_type($sel, "password", '??' . $ENV{BZ_TEST_NEWBIE_PASS});
+ click_and_type($sel, "matchpassword", '??' . $ENV{BZ_TEST_NEWBIE_PASS});
+ submit($sel, '//input[@id="update"]');
+ $sel->title_is('Password Changed');
+ $sel->get_ok("/token.cgi?t=$token&a=cfmpw");
+ $sel->title_is('Token Does Not Exist');
+ $sel->get_ok("/login");
+ $sel->title_is('Log in to Bugzilla');
+ login_ok($sel, $ENV{BZ_TEST_NEWBIE}, "??" . $ENV{BZ_TEST_NEWBIE_PASS});
+ change_password(
+ $sel,
+ "??" . $ENV{BZ_TEST_NEWBIE_PASS},
+ $ENV{BZ_TEST_NEWBIE_PASS},
+ $ENV{BZ_TEST_NEWBIE_PASS}
+ );
+ $sel->title_is("User Preferences");
+
+ logout_ok($sel);
+ open my $fh, '>', '/app/data/mailer.testfile';
+ close $fh;
+
+ $sel->get('/createaccount.cgi');
+ $sel->title_is('Create a new Bugzilla account');
+ click_and_type($sel, 'login', $ENV{BZ_TEST_NEWBIE2});
+ $sel->find_element('//input[@id="etiquette"]', 'xpath')->click();
+ submit($sel, '//input[@value="Create Account"]');
+ $sel->title_is("Request for new user account '$ENV{BZ_TEST_NEWBIE2}' submitted");
+ my ($create_token) = search_mailer_testfile(
+ qr{/token\.cgi\?t=([^&]+)&a=request_new_account}xs
+ );
+ $sel->get("/token.cgi?t=$create_token&a=request_new_account");
+ click_and_type($sel, 'passwd1', $ENV{BZ_TEST_NEWBIE2_PASS});
+ click_and_type($sel, 'passwd2', $ENV{BZ_TEST_NEWBIE2_PASS});
+ submit($sel, '//input[@value="Create"]');
+
+ $sel->title_is('Bugzilla Main Page');
+ $sel->body_text_contains(
+ ["The user account $ENV{BZ_TEST_NEWBIE2} has been created",
+ "successfully"]
+ );
+};
+if ($@) {
+ fail("got exception $@");
+}
+done_testing();
+
+sub submit {
+ my ($sel, $xpath) = @_;
+ $sel->find_element($xpath, 'xpath')->submit();
+}
+
+sub get_token {
+ my $token;
+ my $count = 0;
+ do {
+ sleep 1 if $count++;
+ open my $fh, '<', '/app/data/mailer.testfile';
+ my $content = do {
+ local $/ = undef;
+ <$fh>;
+ };
+ ($token) = $content =~ m!/token\.cgi\?t=3D([^&]+)&a=3Dcfmpw!s;
+ close $fh;
+ } until $token || $count > 60;
+ return $token;
+}
+
+sub search_mailer_testfile {
+ my ($regexp) = @_;
+ my $content = "";
+ my @result;
+ my $count = 0;
+ do {
+ sleep 1 if $count++;
+ open my $fh, '<', '/app/data/mailer.testfile';
+ $content .= do {
+ local $/ = undef;
+ <$fh>;
+ };
+ close $fh;
+ my $decoded = $content;
+ $decoded =~ s/\r\n/\n/gs;
+ $decoded =~ s/=\n//gs;
+ $decoded =~ s/=([[:xdigit:]]{2})/chr(hex($1))/ges;
+ @result = $decoded =~ $regexp;
+ } until @result || $count > 60;
+ return @result;
+}
+
+sub click_and_type {
+ my ($sel, $name, $text) = @_;
+
+ eval {
+ my $el = $sel->find_element(qq{//input[\@name="$name"]}, 'xpath');
+ $el->click();
+ $sel->send_keys_to_active_element($text);
+ pass("found $name and typed $text");
+ };
+ if ($@) {
+ fail("failed to find $name");
+ }
+}
+
+sub click_link {
+ my ($sel, $text) = @_;
+ my $el = $sel->find_element($text, 'link_text');
+ $el->click();
+}
+
+sub change_password {
+ my ($sel, $old, $new1, $new2) = @_;
+ $sel->get_ok("/userprefs.cgi?tab=account");
+ $sel->title_is("User Preferences");
+ click_and_type($sel, "old_password", $old);
+ click_and_type($sel, "new_password1", $new1);
+ click_and_type($sel, "new_password2", $new2);
+ submit($sel, '//input[@value="Submit Changes"]');
+}
+
+sub toggle_require_password_change {
+ my ($sel, $login) = @_;
+ $sel->get_ok("/editusers.cgi");
+ $sel->title_is("Search users");
+ click_and_type($sel, 'matchstr', $login);
+ submit($sel, '//input[@id="search"]');
+ $sel->title_is("Select user");
+ click_link($sel, $login);
+ $sel->find_element('//input[@id="password_change_required"]')->click;
+ submit($sel, '//input[@id="update"]');
+ $sel->title_is("User $login updated");
+}
+
+sub login {
+ my ($sel, $login, $password) = @_;
+
+ $sel->get_ok("/login");
+ $sel->title_is("Log in to Bugzilla");
+ click_and_type($sel, 'Bugzilla_login', $login);
+ click_and_type($sel, 'Bugzilla_password', $password);
+ submit($sel, '//input[@name="GoAheadAndLogIn"]');
+}
+
+sub login_ok {
+ my ($sel) = @_;
+ login(@_);
+ $sel->title_is('Bugzilla Main Page');
+}
+
+sub logout_ok {
+ my ($sel) = @_;
+ $sel->get_ok('/index.cgi?logout=1');
+ $sel->title_is("Logged Out");
+}