Commit eecd85d4 authored by Grant Young's avatar Grant Young Committed by Mark Lapierre

First pass at new automated QA API test for #52703

Checks that archives of two different user projects with the same name aren't the same via checksum.  I.E. a user can't download the archive of another's project by mistake.

To enable the test some enhancements were made.  Namely updating the client module to handle more than one API instance and the creation a custom rest call method that downloads to tmp.
parent 58f3a561
...@@ -13,6 +13,8 @@ module QA ...@@ -13,6 +13,8 @@ module QA
ResourceURLMissingError = Class.new(RuntimeError) ResourceURLMissingError = Class.new(RuntimeError)
attr_reader :api_resource, :api_response attr_reader :api_resource, :api_response
attr_writer :api_client
attr_accessor :user
def api_support? def api_support?
respond_to?(:api_get_path) && respond_to?(:api_get_path) &&
...@@ -29,9 +31,12 @@ module QA ...@@ -29,9 +31,12 @@ module QA
end end
def eager_load_api_client! def eager_load_api_client!
return unless api_client.nil?
api_client.tap do |client| api_client.tap do |client|
# Eager-load the API client so that the personal token creation isn't # Eager-load the API client so that the personal token creation isn't
# taken in account in the actual resource creation timing. # taken in account in the actual resource creation timing.
client.user = user
client.personal_access_token client.personal_access_token
end end
end end
...@@ -76,7 +81,7 @@ module QA ...@@ -76,7 +81,7 @@ module QA
def api_client def api_client
@api_client ||= begin @api_client ||= begin
Runtime::API::Client.new(:gitlab, is_new_session: !current_url.start_with?('http')) Runtime::API::Client.new(:gitlab, is_new_session: !current_url.start_with?('http'), user: user)
end end
end end
......
...@@ -21,7 +21,7 @@ module QA ...@@ -21,7 +21,7 @@ module QA
def fabricate! def fabricate!
populate(:push) populate(:push)
fork.visit! fork.project.visit!
Page::Project::Show.perform(&:new_merge_request) Page::Project::Show.perform(&:new_merge_request)
Page::MergeRequest::New.perform(&:create_merge_request) Page::MergeRequest::New.perform(&:create_merge_request)
......
...@@ -11,7 +11,9 @@ module QA ...@@ -11,7 +11,9 @@ module QA
attribute :id attribute :id
attribute :name attribute :name
attribute :add_name_uuid
attribute :description attribute :description
attribute :standalone
attribute :group do attribute :group do
Group.fabricate! Group.fabricate!
...@@ -38,18 +40,21 @@ module QA ...@@ -38,18 +40,21 @@ module QA
end end
def initialize def initialize
@add_name_uuid = true
@standalone = false
@description = 'My awesome project' @description = 'My awesome project'
@initialize_with_readme = false @initialize_with_readme = false
end end
def name=(raw_name) def name=(raw_name)
@name = "#{raw_name}-#{SecureRandom.hex(8)}" @name = @add_name_uuid ? "#{raw_name}-#{SecureRandom.hex(8)}" : raw_name
end end
def fabricate! def fabricate!
unless @standalone
group.visit! group.visit!
Page::Group::Show.perform(&:go_to_new_project) Page::Group::Show.perform(&:go_to_new_project)
end
Page::Project::New.perform do |page| Page::Project::New.perform do |page|
page.choose_test_namespace page.choose_test_namespace
...@@ -71,19 +76,28 @@ module QA ...@@ -71,19 +76,28 @@ module QA
"/projects/#{CGI.escape(path_with_namespace)}" "/projects/#{CGI.escape(path_with_namespace)}"
end end
def api_get_archive_path(type = 'tar.gz')
"#{api_get_path}/repository/archive.#{type}"
end
def api_post_path def api_post_path
'/projects' '/projects'
end end
def api_post_body def api_post_body
{ post_body = {
namespace_id: group.id,
path: name,
name: name, name: name,
description: description, description: description,
visibility: 'public', visibility: 'public',
initialize_with_readme: @initialize_with_readme initialize_with_readme: @initialize_with_readme
} }
unless @standalone
post_body[:namespace_id] = group.id
post_body[:path] = name
end
post_body
end end
private private
......
...@@ -88,7 +88,7 @@ module QA ...@@ -88,7 +88,7 @@ module QA
}.merge(ldap_post_body) }.merge(ldap_post_body)
end end
def self.fabricate_or_use(username, password) def self.fabricate_or_use(username = nil, password = nil)
if Runtime::Env.signup_disabled? if Runtime::Env.signup_disabled?
self.new.tap do |user| self.new.tap do |user|
user.username = username user.username = username
......
...@@ -6,31 +6,34 @@ module QA ...@@ -6,31 +6,34 @@ module QA
module Runtime module Runtime
module API module API
class Client class Client
attr_reader :address attr_reader :address, :user
def initialize(address = :gitlab, personal_access_token: nil, is_new_session: true) def initialize(address = :gitlab, personal_access_token: nil, is_new_session: true, user: nil)
@address = address @address = address
@personal_access_token = personal_access_token @personal_access_token = personal_access_token
@is_new_session = is_new_session @is_new_session = is_new_session
@user = user
end end
def personal_access_token def personal_access_token
@personal_access_token ||= begin @personal_access_token ||= begin
# you can set the environment variable GITLAB_QA_ACCESS_TOKEN # you can set the environment variable GITLAB_QA_ACCESS_TOKEN
# to use a specific access token rather than create one from the UI # to use a specific access token rather than create one from the UI
Runtime::Env.personal_access_token ||= create_personal_access_token # unless a specific user has been passed
@user.nil? ? Runtime::Env.personal_access_token ||= create_personal_access_token : create_personal_access_token
end end
end end
private private
def create_personal_access_token def create_personal_access_token
Runtime::Browser.visit(@address, Page::Main::Login) if @is_new_session Page::Main::Menu.perform(&:sign_out) if @is_new_session && Page::Main::Menu.perform { |p| p.has_personal_area?(wait: 0) }
do_create_personal_access_token
unless Page::Main::Menu.perform { |p| p.has_personal_area?(wait: 0) }
Runtime::Browser.visit(@address, Page::Main::Login)
Page::Main::Login.perform { |login| login.sign_in_using_credentials(@user) }
end end
def do_create_personal_access_token
Page::Main::Login.perform(&:sign_in_using_credentials)
Resource::PersonalAccessToken.fabricate!.access_token Resource::PersonalAccessToken.fabricate!.access_token
end end
end end
......
# frozen_string_literal: true
require 'securerandom'
require 'digest'
module QA
context 'Create' do
describe 'Compare archives of different user projects with the same name and check they\'re different' do
include Support::Api
before(:all) do
@project_name = "project-archive-download-#{SecureRandom.hex(8)}"
@archive_types = %w(tar.gz tar.bz2 tar zip)
@users = {
user1: { username: Runtime::Env.gitlab_qa_username_1, password: Runtime::Env.gitlab_qa_password_1 },
user2: { username: Runtime::Env.gitlab_qa_username_2, password: Runtime::Env.gitlab_qa_password_2 }
}
@users.each do |_, user_info|
user_info[:user] = Resource::User.fabricate_or_use(user_info[:username], user_info[:password])
user_info[:api_client] = Runtime::API::Client.new(:gitlab, user: user_info[:user])
user_info[:api_client].personal_access_token
user_info[:project] = create_project(user_info[:user], user_info[:api_client], @project_name)
Page::Main::Menu.perform(&:sign_out)
end
end
it 'download archives of each user project then check they are different' do
archive_checksums = {}
@users.each do |user_key, user_info|
archive_checksums[user_key] = {}
@archive_types.each do |type|
archive_path = download_project_archive_via_api(user_info[:api_client], user_info[:project], type).path
archive_checksums[user_key][type] = Digest::MD5.hexdigest(File.read(archive_path))
end
end
QA::Runtime::Logger.debug("Archive checksums are #{archive_checksums}")
expect(archive_checksums[:user1]).not_to include(archive_checksums[:user2])
end
def create_project(user, api_client, project_name)
project = Resource::Project.fabricate! do |project|
project.standalone = true
project.add_name_uuid = false
project.name = project_name
project.path_with_namespace = "#{user.name}/#{project_name}"
project.user = user
project.api_client = api_client
end
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.file_name = 'README.md'
push.file_content = '# This is a test project'
push.commit_message = 'Add README.md'
push.user = user
end
project
end
def download_project_archive_via_api(api_client, project, type = 'tar.gz')
get_project_archive_zip = Runtime::API::Request.new(api_client, project.api_get_archive_path(type))
project_archive_download = get(get_project_archive_zip.url, raw_response: true)
expect(project_archive_download.code).to eq(200)
project_archive_download.file
end
end
end
end
...@@ -16,11 +16,12 @@ module QA ...@@ -16,11 +16,12 @@ module QA
e.response e.response
end end
def get(url) def get(url, raw_response: false)
RestClient::Request.execute( RestClient::Request.execute(
method: :get, method: :get,
url: url, url: url,
verify_ssl: false) verify_ssl: false,
raw_response: raw_response)
rescue RestClient::ExceptionWithResponse => e rescue RestClient::ExceptionWithResponse => e
e.response e.response
end end
......
...@@ -16,26 +16,56 @@ describe QA::Runtime::API::Client do ...@@ -16,26 +16,56 @@ describe QA::Runtime::API::Client do
end end
describe '#personal_access_token' do describe '#personal_access_token' do
context 'when QA::Runtime::Env.personal_access_token is present' do context 'when user is nil and QA::Runtime::Env.personal_access_token is present' do
before do before do
allow(QA::Runtime::Env).to receive(:personal_access_token).and_return('a_token') allow(QA::Runtime::Env).to receive(:personal_access_token).and_return('a_token')
end end
it 'returns specified token from env' do it 'returns specified token from env' do
expect(described_class.new.personal_access_token).to eq 'a_token' expect(subject.personal_access_token).to eq 'a_token'
end end
end end
context 'when QA::Runtime::Env.personal_access_token is nil' do context 'when user is present and QA::Runtime::Env.personal_access_token is nil' do
before do before do
allow(QA::Runtime::Env).to receive(:personal_access_token).and_return(nil) allow(QA::Runtime::Env).to receive(:personal_access_token).and_return(nil)
end end
it 'returns a created token' do it 'returns a created token' do
subject { described_class.new(user: { username: 'foo' }) }
expect(subject).to receive(:create_personal_access_token).and_return('created_token') expect(subject).to receive(:create_personal_access_token).and_return('created_token')
expect(subject.personal_access_token).to eq 'created_token' expect(subject.personal_access_token).to eq 'created_token'
end end
end end
context 'when user is nil and QA::Runtime::Env.personal_access_token is nil' do
before do
allow(QA::Runtime::Env).to receive(:personal_access_token).and_return(nil)
end
it 'returns a created token' do
client = described_class.new
expect(client).to receive(:create_personal_access_token).and_return('created_token')
expect(client.personal_access_token).to eq 'created_token'
end
end
context 'when user is present and QA::Runtime::Env.personal_access_token is present' do
before do
allow(QA::Runtime::Env).to receive(:personal_access_token).and_return('a_token')
end
it 'returns a created token' do
client = described_class.new(user: { username: 'foo' })
expect(client).to receive(:create_personal_access_token).and_return('created_token')
expect(client.personal_access_token).to eq 'created_token'
end
end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment