Commit 0a1f3f6a authored by Aaron Gable's avatar Aaron Gable Committed by Commit Bot

Remove defunct Rietveld end-to-end tests

R=tandrii@chromium.org

Bug: 770019
Change-Id: I55d74d67281bd3f79cfd5ba9f57eea082359573e
Reviewed-on: https://chromium-review.googlesource.com/693034
Commit-Queue: Aaron Gable <agable@chromium.org>
Reviewed-by: 's avatarAndrii Shyshkalov <tandrii@chromium.org>
parent 35c5b9ad
......@@ -63,54 +63,6 @@ def CommonChecks(input_api, output_api, tests_to_black_list):
return results
def RunGitClTests(input_api, output_api):
"""Run all the shells scripts in the directory test.
"""
if input_api.platform == 'win32':
# Skip for now as long as the test scripts are bash scripts.
return []
# First loads a local Rietveld instance.
import sys
old_sys_path = sys.path
try:
sys.path = [input_api.PresubmitLocalPath()] + sys.path
from testing_support import local_rietveld
server = local_rietveld.LocalRietveld()
finally:
sys.path = old_sys_path
results = []
try:
# Start a local rietveld instance to test against.
server.start_server()
test_path = input_api.os_path.abspath(
input_api.os_path.join(input_api.PresubmitLocalPath(), 'tests'))
# test-lib.sh is not an actual test so it should not be run.
NON_TEST_FILES = ('test-lib.sh')
for test in input_api.os_listdir(test_path):
if test in NON_TEST_FILES or not test.endswith('.sh'):
continue
print('Running %s' % test)
try:
if input_api.verbose:
input_api.subprocess.check_call(
[input_api.os_path.join(test_path, test)], cwd=test_path)
else:
input_api.subprocess.check_output(
[input_api.os_path.join(test_path, test)], cwd=test_path,
stderr=input_api.subprocess.STDOUT)
except (OSError, input_api.subprocess.CalledProcessError), e:
results.append(output_api.PresubmitError('%s failed\n%s' % (test, e)))
except local_rietveld.Failure, e:
results.append(output_api.PresubmitError('\n'.join(str(i) for i in e.args)))
finally:
server.stop_server()
return results
def CheckChangeOnUpload(input_api, output_api):
# Do not run integration tests on upload since they are way too slow.
tests_to_black_list = [
......@@ -128,5 +80,4 @@ def CheckChangeOnCommit(input_api, output_api):
output.extend(input_api.canned_checks.CheckDoNotSubmit(
input_api,
output_api))
output.extend(RunGitClTests(input_api, output_api))
return output
......@@ -14,8 +14,6 @@ class Infra(config_util.Config):
@staticmethod
def fetch_spec(props):
# This is used by [depot_tools]/testing_support/local_rietveld.py
managed = props.get('managed', 'false').lower() == 'true'
return {
'type': 'gclient_git',
'gclient_git_spec': {
......@@ -24,7 +22,7 @@ class Infra(config_util.Config):
'name' : 'infra',
'url' : 'https://chromium.googlesource.com/infra/infra.git',
'deps_file': '.DEPS.git',
'managed' : managed,
'managed' : False,
}
],
},
......
#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Setups a local Rietveld instance to test against a live server for
integration tests.
It makes sure Google AppEngine SDK is found, download Rietveld and Django code
if necessary and starts the server on a free inbound TCP port.
"""
import logging
import optparse
import os
import shutil
import socket
import sys
import tempfile
import time
try:
import subprocess2
except ImportError:
sys.path.append(
os.path.join(os.path.dirname(os.path.abspath(__file__)), '..'))
import subprocess2
DEPOT_TOOLS=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
class Failure(Exception):
pass
def test_port(port):
s = socket.socket()
try:
return s.connect_ex(('127.0.0.1', port)) == 0
finally:
s.close()
def find_free_port(start_port):
"""Search for a free port starting at specified port."""
for port in xrange(start_port, (2<<16)):
if not test_port(port):
return port
raise Failure('Having issues finding an available port')
class LocalRietveld(object):
"""Downloads everything needed to run a local instance of Rietveld."""
def __init__(self, base_dir=None):
# Paths
self.base_dir = base_dir
if not self.base_dir:
self.base_dir = os.path.dirname(os.path.abspath(__file__))
self.rietveld = os.path.join(self.base_dir, '_rietveld')
self.infra = os.path.join(self.base_dir, '_infra')
self.rietveld_app = os.path.join(
self.infra, 'infra', 'appengine', 'chromium_rietveld')
self.dev_app = os.path.join(
self.infra, 'google_appengine', 'dev_appserver.py')
self.test_server = None
self.port = None
self.tempdir = None
def install_prerequisites(self):
if os.path.exists(self.rietveld):
print "Removing old rietveld dir"
shutil.rmtree(self.rietveld)
sdk_path = os.path.join(self.base_dir, 'google_appengine')
if os.path.exists(sdk_path):
print "Removing old appengine SDK dir"
shutil.rmtree(sdk_path)
previous = os.environ.get('DEPOT_TOOLS_UPDATE')
os.environ['DEPOT_TOOLS_UPDATE'] = '0'
try:
if not os.path.isfile(os.path.join(self.infra, '.gclient')):
print('Checking out infra...')
shutil.rmtree(self.infra, ignore_errors=True)
try:
os.makedirs(self.infra)
subprocess2.call(
[sys.executable, os.path.join(DEPOT_TOOLS, 'fetch.py'),
'--force', 'infra', '--managed=true'],
cwd=self.infra)
except (OSError, subprocess2.CalledProcessError), e:
raise Failure('Failed to clone infra. \n%s' % e)
else:
print('Syncing infra...')
try:
subprocess2.call(
[sys.executable, os.path.join(DEPOT_TOOLS, 'gclient.py'),
'sync', '--force'],
cwd=self.infra)
except (OSError, subprocess2.CalledProcessError), e:
raise Failure('Failed to sync infra. \n%s' % e)
finally:
if previous is None:
del os.environ['DEPOT_TOOLS_UPDATE']
else:
os.environ['DEPOT_TOOLS_UPDATE'] = previous
def start_server(self, verbose=False):
self.install_prerequisites()
assert not self.tempdir
self.tempdir = tempfile.mkdtemp(prefix='rietveld_test')
self.port = find_free_port(10000)
admin_port = find_free_port(self.port + 1)
if verbose:
stdout = stderr = None
else:
stdout = subprocess2.PIPE
stderr = subprocess2.STDOUT
cmd = [
sys.executable,
self.dev_app,
'./app.yaml', # Explicitly specify file to avoid bringing up backends.
'--port', str(self.port),
'--admin_port', str(admin_port),
'--storage', self.tempdir,
'--clear_search_indexes',
'--skip_sdk_update_check',
]
# CHEAP TRICK
# By default you only want to bind on loopback but I'm testing over a
# headless computer so it's useful to be able to access the test instance
# remotely.
if os.environ.get('GAE_LISTEN_ALL', '') == 'true':
cmd.extend(('-a', '0.0.0.0'))
logging.info(' '.join(cmd))
self.test_server = subprocess2.Popen(
cmd, stdout=stdout, stderr=stderr, cwd=self.rietveld_app)
# Loop until port 127.0.0.1:port opens or the process dies.
while not test_port(self.port):
self.test_server.poll()
if self.test_server.returncode is not None:
if not verbose:
out = self.test_server.communicate()[0]
shutil.rmtree(self.tempdir)
self.tempdir = None
raise Failure(
'Test rietveld instance failed early on port %s\n%s' %
(self.port, out))
time.sleep(0.01)
def stop_server(self):
if self.test_server:
try:
self.test_server.kill()
except OSError:
pass
self.test_server.wait()
self.test_server = None
self.port = None
if self.tempdir:
shutil.rmtree(self.tempdir)
self.tempdir = None
def main():
parser = optparse.OptionParser()
parser.add_option('-v', '--verbose', action='store_true')
options, args = parser.parse_args()
if args:
parser.error('Unknown arguments: %s' % ' '.join(args))
instance = LocalRietveld()
try:
instance.start_server(verbose=options.verbose)
print 'Local rietveld instance started on port %d' % instance.port
while True:
time.sleep(0.1)
finally:
instance.stop_server()
if __name__ == '__main__':
main()
#!/usr/bin/env bash
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Check that abandoning a branch also abandons its issue.
set -e
. ./test-lib.sh
setup_git_remote
setup_git_checkout
(
set -e
cd git_checkout
git config rietveld.server localhost:10000
# Create a branch and give it an issue.
git checkout -q -b abandoned
echo "some work done on a branch" >> test
git add test; git commit -q -m "branch work"
export GIT_EDITOR=$(which true)
test_expect_success "upload succeeds" \
"$GIT_CL upload --no-oauth2 -m test master | grep -q 'Issue created'"
# Switch back to master, delete the branch.
git checkout master
git branch -D abandoned
# Verify that "status" doesn't know about it anymore.
# The "exit" trickiness is inverting the exit status of grep.
test_expect_success "git-cl status dropped abandoned branch" \
"$GIT_CL_STATUS | grep -q abandoned && exit 1 || exit 0"
)
SUCCESS=$?
cleanup
if [ $SUCCESS == 0 ]; then
echo PASS
fi
#!/usr/bin/env bash
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
set -e
. ./test-lib.sh
setup_git_remote
setup_git_checkout
(
set -e
cd git_checkout
git checkout -q --track -b work origin
echo "some work done on a branch" >> test
git add test; git commit -q -m "branch work"
echo "some other work done on a branch" >> test
git add test; git commit -q -m "branch work"
test_expect_success "git-cl upload wants a server" \
"$GIT_CL upload --no-oauth2 2>&1 | grep -q 'You must configure'"
git config rietveld.server localhost:10000
test_expect_success "git-cl status has no issue" \
"$GIT_CL_STATUS | grep -q 'No issue assigned'"
# Prevent the editor from coming up when you upload.
export GIT_EDITOR=$(which true)
test_expect_success "upload succeeds (needs a server running on localhost)" \
"$GIT_CL upload --no-oauth2 -m test master | grep -q 'Issue created'"
test_expect_success "git-cl status now knows the issue" \
"$GIT_CL_STATUS | grep -q 'Issue number'"
# Push a description to this URL.
URL=$($GIT_CL_STATUS | sed -ne '/Issue number/s/[^(]*(\(.*\))/\1/p')
curl --cookie dev_appserver_login="test@example.com:False" \
--data-urlencode subject="test" \
--data-urlencode description="foo-quux" \
--data-urlencode xsrf_token="$(print_xsrf_token)" \
$URL/edit
test_expect_success "git-cl land ok" \
"$GIT_CL land -f --no-oauth2"
test_expect_success "branch still has an issue" \
"$GIT_CL_STATUS | grep -q 'Issue number'"
git checkout -q master > /dev/null 2>&1
git pull -q > /dev/null 2>&1
test_expect_success "committed code has proper description" \
"git show | grep -q 'foo-quux'"
cd $GITREPO_PATH
test_expect_success "upstream repo has our commit" \
"git log master 2>/dev/null | grep -q 'foo-quux'"
)
SUCCESS=$?
cleanup
if [ $SUCCESS == 0 ]; then
echo PASS
fi
#!/usr/bin/env bash
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Tests the "preupload and preland hooks" functionality, which lets you run
# hooks by installing a script into .git/hooks/pre-cl-* first.
set -e
. ./test-lib.sh
setup_git_remote
setup_git_checkout
setup_hooks() {
upload_retval=$1
land_retval=$2
echo > PRESUBMIT.py <<END
def CheckChangeOnUpload(input_api, output_api):
return $upload_retval
def CheckChangeOnCommit(input_api, output_api):
return $land_retval
END
}
(
set -e
cd git_checkout
# We need a server set up, but we don't use it. git config rietveld.server localhost:1
# Install hooks that will fail on upload and commit
setup_hooks 1 1
echo "some work done" >> test
git add test; git commit -q -m "work"
# Verify git cl upload fails.
test_expect_failure "git-cl upload hook fails" "$GIT_CL upload master"
# Verify git cl land fails.
test_expect_failure "git-cl land hook fails" "$GIT_CL land master"
)
SUCCESS=$?
#cleanup
if [ $SUCCESS == 0 ]; then
echo PASS
fi
#!/usr/bin/env bash
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
set -e
. ./test-lib.sh
setup_git_remote
setup_git_checkout
(
set -e
cd git_checkout
git config rietveld.server localhost:10000
export GIT_EDITOR=$(which true)
git checkout -q -b work
echo "ben@chromium.org" > OWNERS
cat <<END > PRESUBMIT.py
def CheckChangeOnCommit(input_api, output_api):
return input_api.canned_checks.CheckOwners(input_api, output_api)
CheckChangeOnUpload = CheckChangeOnCommit
END
git add OWNERS PRESUBMIT.py ; git commit -q -m "add OWNERS"
test_expect_success "upload succeeds (needs a server running on localhost)" \
"$GIT_CL upload --no-oauth2 -m test master | grep -q 'Issue created'"
test_expect_failure "git-cl land fails w/ missing LGTM" \
"$GIT_CL land -f --no-oauth2"
)
SUCCESS=$?
cleanup
if [ $SUCCESS == 0 ]; then
echo PASS
fi
#!/usr/bin/env bash
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
set -e
. ./test-lib.sh
setup_git_remote
setup_git_checkout
(
set -e
cd git_checkout
git checkout -q -b work
echo "some work done on a branch" >> test
git add test; git commit -q -m "branch work"
git config rietveld.server localhost:10000
# Prevent the editor from coming up when you upload.
export GIT_EDITOR=$(which true)
test_expect_success "upload succeeds (needs a server running on localhost)" \
"$GIT_CL upload --no-oauth2 -m test master | grep -q 'Issue created'"
test_expect_success "git-cl status now knows the issue" \
"$GIT_CL_STATUS | grep -q 'Issue number'"
ISSUE=$($GIT_CL_STATUS | awk '$0 ~ "Issue number:" { print $3 }')
git checkout -q -b test2 master
test_expect_success "$GIT_CL patch $ISSUE --no-oauth2"
)
SUCCESS=$?
cleanup
if [ $SUCCESS == 0 ]; then
echo PASS
fi
#!/usr/bin/env bash
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
set -e
. ./test-lib.sh
setup_git_remote
setup_git_checkout
(
set -e
cd git_checkout
cat > .git/hooks/post-cl-land << _EOF
#!/usr/bin/env bash
git branch -m COMMITTED
_EOF
chmod +x .git/hooks/post-cl-land
git config rietveld.server localhost:1
git checkout -q -t origin/master -b work
echo "some work done" >> test
git add test; git commit -q -m "work \
TBR=foo"
test_expect_success "landed code" \
"$GIT_CL land --no-oauth2 -f --bypass-hooks -m 'land'"
test_expect_success "post-cl-land hook executed" \
"git symbolic-ref HEAD | grep -q COMMITTED"
)
SUCCESS=$?
cleanup
if [ $SUCCESS == 0 ]; then
echo PASS
fi
#!/usr/bin/env bash
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
set -e
. ./test-lib.sh
setup_git_remote
setup_git_checkout
(
set -e
cd git_checkout
git checkout -q -t origin/master -b work
echo "some work done on a branch" >> test
git add test; git commit -q -m "branch work"
echo "some other work done on a branch" >> test
git add test; git commit -q -m "branch work"
test_expect_success "git-cl upload wants a server" \
"$GIT_CL upload --no-oauth2 2>&1 | grep -q 'You must configure'"
git config rietveld.server localhost:10000
test_expect_success "git-cl status has no issue" \
"$GIT_CL_STATUS | grep -q 'No issue assigned'"
# Prevent the editor from coming up when you upload.
export EDITOR=$(which true)
test_expect_success "upload succeeds (needs a server running on localhost)" \
"$GIT_CL upload --no-oauth2 -t test master | \
grep -q 'Issue created'"
test_expect_success "git-cl status now knows the issue" \
"$GIT_CL_STATUS | grep -q 'Issue number'"
# Check to see if the description contains the local commit messages.
# Should contain 'branch work' x 2.
test_expect_success "git-cl status has the right description for the log" \
"[ $($GIT_CL_STATUS --field desc | egrep '^branch work$' -c) -eq 2 ]"
test_expect_success "git-cl status has the right subject from message" \
"$GIT_CL_STATUS --field desc | head -n 1 | grep -q '^test$'"
test_expect_success "git-cl land ok" \
"$GIT_CL land --bypass-hooks"
git fetch origin
git checkout origin/master
test_expect_success "committed code has proper summary" \
"[ $(git log -n 1 --pretty=format:%s | egrep '^test$' -c) -eq 1 ]"
test_expect_success "committed code has proper description" \
"[ $(git log -n 1 --pretty=format:%b | egrep '^branch work$' -c) -eq 2 ]"
# # Have to sleep to let the server return the new status.
# sleep 5
# test_expect_success "branch issue is closed" \
# "$GIT_CL_STATUS | grep -q 'work :.*closed'"
)
SUCCESS=$?
cleanup
if [ $SUCCESS == 0 ]; then
echo PASS
fi
This diff is collapsed.
#!/usr/bin/env bash
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# We should save a change's description when an upload fails.
set -e
. ./test-lib.sh
# Back up any previously-saved description the user might have.
BACKUP_FILE="$HOME/.git_cl_description_backup"
BACKUP_FILE_TMP="$BACKUP_FILE.tmp"
if [ -e "$BACKUP_FILE" ]; then
mv "$BACKUP_FILE" "$BACKUP_FILE_TMP"
fi
setup_git_remote
setup_git_checkout
(
set -e
cd git_checkout
DESC="this is the description"
# Create a branch and check in a file.
git checkout -q --track -b work origin
echo foo >> test
git add test; git commit -q -m "$DESC"
# Try to upload the change to an unresolvable hostname; git-cl should fail.
export GIT_EDITOR=$(which true)
git config rietveld.server bogus.example.com:80
test_expect_failure "uploading to bogus server" \
"$GIT_CL upload --no-oauth2 2>/dev/null"
# Check that the change's description was saved.
test_expect_success "description was backed up" \
"grep -q '$DESC' '$BACKUP_FILE'"
)
SUCCESS=$?
cleanup
# Restore the previously-saved description.
rm -f "$BACKUP_FILE"
if [ -e "$BACKUP_FILE_TMP" ]; then
mv "$BACKUP_FILE_TMP" "$BACKUP_FILE"
fi
if [ $SUCCESS == 0 ]; then
echo PASS
fi
#!/usr/bin/env bash
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Check that we're able to submit from a directory that doesn't exist on the
# trunk. This tests for a previous bug where we ended up with an invalid CWD
# after switching to the merge branch.
set -e
. ./test-lib.sh
setup_git_remote
setup_git_checkout
(
set -e
cd git_checkout
git config rietveld.server localhost:10000
# Create a branch and give it an issue.
git checkout -q -b new
mkdir dir
cd dir
echo "some work done on a branch" >> test
git add test; git commit -q -m "branch work"
export GIT_EDITOR=$(which true)
test_expect_success "upload succeeds" \
"$GIT_CL upload --no-oauth2 -m test master | grep -q 'Issue created'"
test_expect_success "git-cl lands ok" \
"$GIT_CL land -f --no-oauth2"
)
SUCCESS=$?
cleanup
if [ $SUCCESS == 0 ]; then
echo PASS
fi
#!/usr/bin/env bash
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Abort on error.
set -e
export DEPOT_TOOLS_UPDATE=0
export PYTHONUNBUFFERED=
PWD=$(pwd)
GITREPO_PATH=$PWD/git_remote
GITREPO_URL=file://$GITREPO_PATH
PATH="$(dirname $PWD):$PATH"
GIT_CL=$(dirname $PWD)/git-cl
GIT_CL_STATUS="$GIT_CL status -f"
# Set up a git repo that has a few commits to master.
setup_git_remote() {
echo "Setting up test upstream git repo..."
rm -rf git_remote
mkdir git_remote
(
cd git_remote
git init -q
git config user.name 'TestDood'
git config user.email 'TestDood@example.com'
echo "test" > test
git add test
git commit -qam "initial commit"
echo "test2" >> test
git commit -qam "second commit"
# Hack: make sure master is not the current branch
# otherwise push will give a warning
git checkout -q --detach master
)
}
# Set up a git checkout of the repo.
setup_git_checkout() {
echo "Setting up test git repo..."
rm -rf git_checkout
git clone -q $GITREPO_URL git_checkout
(
cd git_checkout
git config user.name 'TestDood'
git config user.email 'TestDood@example.com'
)
}
cleanup() {
rm -rf git_remote git_checkout
}
# Usage: test_expect_success "description of test" "test code".
test_expect_success() {
echo "TESTING: $1"
exit_code=0
sh -c "$2" || exit_code=$?
if [ $exit_code != 0 ]; then
echo "FAILURE: $1"
return $exit_code
fi
}
# Usage: test_expect_failure "description of test" "test code".
test_expect_failure() {
echo "TESTING: $1"
exit_code=0
sh -c "$2" || exit_code=$?
if [ $exit_code = 0 ]; then
echo "SUCCESS, BUT EXPECTED FAILURE: $1"
return $exit_code
fi
}
# Grab the XSRF token from the review server and print it to stdout.
print_xsrf_token() {
curl --cookie dev_appserver_login="test@example.com:False" \
--header 'X-Requesting-XSRF-Token: 1' \
http://localhost:10000/xsrf_token 2>/dev/null
}
#!/usr/bin/env bash
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
set -e
. ./test-lib.sh
setup_git_remote
setup_git_checkout
(
set -e
cd git_checkout
git checkout -q -b work HEAD^
git checkout -q -t -b work2 work
echo "some work done on a branch that tracks a local branch" >> test
git add test; git commit -q -m "local tracking branch work"
git config rietveld.server localhost:10000
# Prevent the editor from coming up when you upload.
export GIT_EDITOR=$(which true)
test_expect_success "upload succeeds (needs a server running on localhost)" \
"$GIT_CL upload --no-oauth2 -m test | grep -q 'Issue created'"
)
SUCCESS=$?
cleanup
if [ $SUCCESS == 0 ]; then
echo PASS
fi
#!/usr/bin/env bash
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
set -e
. ./test-lib.sh
setup_git_remote
setup_git_checkout
(
set -e
cd git_checkout
git checkout -q -b work HEAD^
echo "some work done on a branch" >> test
git add test; git commit -q -m "branch work"
git config rietveld.server localhost:10000
# Prevent the editor from coming up when you upload.
export GIT_EDITOR=$(which true)
test_expect_success "upload succeeds (needs a server running on localhost)" \
"$GIT_CL upload --no-oauth2 -m test | grep -q 'Issue created'"
test_expect_failure "description shouldn't contain unrelated commits" \
"$GIT_CL_STATUS | grep -q 'second commit'"
)
SUCCESS=$?
cleanup
if [ $SUCCESS == 0 ]; then
echo PASS
fi
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