From mboxrd@z Thu Jan 1 00:00:00 1970 From: Ricardo Martincoski Date: Sun, 29 Apr 2018 11:33:49 -0300 Subject: [Buildroot] [RFC PATCH v4] support/testing: test extra download with site method git In-Reply-To: <20180429143349.24010-1-ricardo.martincoski@gmail.com> References: <20180429143349.24010-1-ricardo.martincoski@gmail.com> Message-ID: <20180429143349.24010-13-ricardo.martincoski@gmail.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: buildroot@busybox.net Add one test case to ensure the use of extra download works for git packages: - an extra download is correctly downloaded using wget after the main download finished using the git backend; - when the main download using the git backend fails, the build fails; - when the extra download using wget fails, the build fails. Reuse the commit in the static repo. Add required infra and fixture: - a HttpServer class, that starts a http server in the host machine to emulate a remote http server under the control of the test; - a file to be served by the http server; - a br2-external (git-extra-download) with one package for each part of the test case. Since the HttpServer is similar to GitRemote, extract the commonalities to a new base class called Server. Signed-off-by: Ricardo Martincoski Cc: Luca Ceresoli Cc: Thomas Petazzoni Cc: Yann E. MORIN --- Changes v3 -> v4: - new patch In the master branch (7a801da8e): https://gitlab.com/RicardoMartincoski/buildroot/-/jobs/65546799 master + these 2 patches: http://patchwork.ozlabs.org/patch/904722/ http://patchwork.ozlabs.org/patch/904721/ https://gitlab.com/RicardoMartincoski/buildroot/-/jobs/65550316 I use docker only with the Buildroot image for the test infra. Sorry, I give up for now on trying to run apache on the docker image. As a midground solution between: - adding more files to http://autobuild.buildroot.net/artefacts/ that won't scale well if we need different files for different test cases; - installing a full web server to the docker image auto-loading as root when the container is started as user and allowing the test infra to copy files to the served path as user; and inspired by this article: https://www.pcsuggest.com/best-lightweight-web-server-linux/ I created this RFC patch using SimpleHTTPServer being started by the test infra as a user. I know it is weird to use pexpect to fork a server written in Python, but it has these advantages: - theoretically replacing SimpleHTTPServer with a similar solution (say the busybox httpd) in the future would require only small changes to the test infra code; - SimpleHTTPServer is already on the docker image, busybox isn't, so no need to change the Dockerfile, generate the image, publish it and update the docker image tag on .gitlab-ci.yml; - the log file generated by the server is handled in the same way as other log files generated by the test infra; --- .gitlab-ci.yml | 1 + support/testing/infra/server.py | 39 ++++++++++++++++++++ .../br2-external/git-extra-download/Config.in | 0 .../br2-external/git-extra-download/external.desc | 1 + .../br2-external/git-extra-download/external.mk | 6 +++ .../package/extra-fails/extra-fails.hash | 3 ++ .../package/extra-fails/extra-fails.mk | 12 ++++++ .../package/main-fails/main-fails.hash | 3 ++ .../package/main-fails/main-fails.mk | 12 ++++++ .../git-extra-download/package/ok/ok.hash | 3 ++ .../git-extra-download/package/ok/ok.mk | 12 ++++++ support/testing/tests/download/gitremote.py | 43 ++++------------------ support/testing/tests/download/http-server/extra | 1 + support/testing/tests/download/httpserver.py | 14 +++++++ support/testing/tests/download/test_git.py | 21 +++++++++++ 15 files changed, 135 insertions(+), 36 deletions(-) create mode 100644 support/testing/infra/server.py create mode 100644 support/testing/tests/download/br2-external/git-extra-download/Config.in create mode 100644 support/testing/tests/download/br2-external/git-extra-download/external.desc create mode 100644 support/testing/tests/download/br2-external/git-extra-download/external.mk create mode 100644 support/testing/tests/download/br2-external/git-extra-download/package/extra-fails/extra-fails.hash create mode 100644 support/testing/tests/download/br2-external/git-extra-download/package/extra-fails/extra-fails.mk create mode 100644 support/testing/tests/download/br2-external/git-extra-download/package/main-fails/main-fails.hash create mode 100644 support/testing/tests/download/br2-external/git-extra-download/package/main-fails/main-fails.mk create mode 100644 support/testing/tests/download/br2-external/git-extra-download/package/ok/ok.hash create mode 100644 support/testing/tests/download/br2-external/git-extra-download/package/ok/ok.mk create mode 100644 support/testing/tests/download/http-server/extra create mode 100644 support/testing/tests/download/httpserver.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 26e2af3799..5df21b8787 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -266,6 +266,7 @@ tests.core.test_rootfs_overlay.TestRootfsOverlay: *runtime_test tests.core.test_timezone.TestGlibcAllTimezone: *runtime_test tests.core.test_timezone.TestGlibcNonDefaultLimitedTimezone: *runtime_test tests.core.test_timezone.TestNoTimezone: *runtime_test +tests.download.test_git.TestGitExtraDownload: *runtime_test tests.download.test_git.TestGitHash: *runtime_test tests.download.test_git.TestGitRefs: *runtime_test tests.fs.test_ext.TestExt2: *runtime_test diff --git a/support/testing/infra/server.py b/support/testing/infra/server.py new file mode 100644 index 0000000000..0fbffdf846 --- /dev/null +++ b/support/testing/infra/server.py @@ -0,0 +1,39 @@ +# subprocess does not kill the child daemon when a test case fails by raising +# an exception. So use pexpect instead. +import pexpect + +import infra + + +class Server(object): + def __init__(self, builddir, serveddir, logtofile, daemon_cmd, port_arg, port_initial, port_last, good_msg, bad_msg): + """ + Start a local server. + + In order to support test cases in parallel, select the port the + server will listen to in runtime. Since there is no reliable way + to allocate the port prior to starting the server (another + process in the host machine can use the port between it is + selected from a list and it is really allocated to the server) + try to start the server in a port and in the case it is already + in use, try the next one in the allowed range. + """ + self.name = self.__class__.__name__.lower() + self.daemon = None + self.port = None + self.logfile = infra.open_log_file(builddir, self.name, logtofile) + + for port in range(port_initial, port_last + 1): + cmd = daemon_cmd + [port_arg.format(port=port)] + self.logfile.write("> starting {} with 'cd {} && {}'\n".format(self.name, serveddir, " ".join(cmd))) + self.daemon = pexpect.spawn(cmd[0], cmd[1:], logfile=self.logfile, cwd=serveddir) + ret = self.daemon.expect(good_msg + bad_msg) + if ret < len(good_msg): + self.port = port + return + raise SystemError("Could not find a free port to run {}".format(self.name)) + + def stop(self): + if self.daemon is None: + return + self.daemon.terminate(force=True) diff --git a/support/testing/tests/download/br2-external/git-extra-download/Config.in b/support/testing/tests/download/br2-external/git-extra-download/Config.in new file mode 100644 index 0000000000..e69de29bb2 diff --git a/support/testing/tests/download/br2-external/git-extra-download/external.desc b/support/testing/tests/download/br2-external/git-extra-download/external.desc new file mode 100644 index 0000000000..6ebd5a534d --- /dev/null +++ b/support/testing/tests/download/br2-external/git-extra-download/external.desc @@ -0,0 +1 @@ +name: GIT_EXTRA_DOWNLOAD diff --git a/support/testing/tests/download/br2-external/git-extra-download/external.mk b/support/testing/tests/download/br2-external/git-extra-download/external.mk new file mode 100644 index 0000000000..c6080f571b --- /dev/null +++ b/support/testing/tests/download/br2-external/git-extra-download/external.mk @@ -0,0 +1,6 @@ +include $(sort $(wildcard $(BR2_EXTERNAL_GIT_EXTRA_DOWNLOAD_PATH)/package/*/*.mk)) + +# Get the git server port number from the test infra +GITREMOTE_PORT_NUMBER ?= 9418 +# Get the http server port number from the test infra +HTTP_SERVER_PORT_NUMBER ?= 8000 diff --git a/support/testing/tests/download/br2-external/git-extra-download/package/extra-fails/extra-fails.hash b/support/testing/tests/download/br2-external/git-extra-download/package/extra-fails/extra-fails.hash new file mode 100644 index 0000000000..89b1b1f682 --- /dev/null +++ b/support/testing/tests/download/br2-external/git-extra-download/package/extra-fails/extra-fails.hash @@ -0,0 +1,3 @@ +sha256 1e6bc73fabdcce8857361e36e3c812c4ee42d8ffa30d56492bc56f8fcad7eb90 extra-fails-a238b1dfcd825d47d834af3c5223417c8411d90d.tar.gz +sha256 b9e68e1bea3e5b19ca6b2f98b73a54b73daafaa250484902e09982e07a12e733 notfound +sha256 da68f54607d5f5644954096ce1597c006c5bb9f2497e07441bf064b81003ef8a file diff --git a/support/testing/tests/download/br2-external/git-extra-download/package/extra-fails/extra-fails.mk b/support/testing/tests/download/br2-external/git-extra-download/package/extra-fails/extra-fails.mk new file mode 100644 index 0000000000..dcf3ebe7a6 --- /dev/null +++ b/support/testing/tests/download/br2-external/git-extra-download/package/extra-fails/extra-fails.mk @@ -0,0 +1,12 @@ +################################################################################ +# +# extra-fails +# +################################################################################ + +EXTRA_FAILS_VERSION = a238b1dfcd825d47d834af3c5223417c8411d90d +EXTRA_FAILS_SITE = git://localhost:$(GITREMOTE_PORT_NUMBER)/repo.git +EXTRA_FAILS_EXTRA_DOWNLOADS = http://localhost:$(HTTP_SERVER_PORT_NUMBER)/notfound +EXTRA_FAILS_LICENSE_FILES = file + +$(eval $(generic-package)) diff --git a/support/testing/tests/download/br2-external/git-extra-download/package/main-fails/main-fails.hash b/support/testing/tests/download/br2-external/git-extra-download/package/main-fails/main-fails.hash new file mode 100644 index 0000000000..ad81243751 --- /dev/null +++ b/support/testing/tests/download/br2-external/git-extra-download/package/main-fails/main-fails.hash @@ -0,0 +1,3 @@ +sha256 cd6851ef519a83345e4547f376b33d6bbd622d4ccbb234af9997c43854c602de main-fails-a238b1dfcd825d47d834af3c5223417c8411d90d.tar.gz +sha256 b9e68e1bea3e5b19ca6b2f98b73a54b73daafaa250484902e09982e07a12e733 extra +sha256 da68f54607d5f5644954096ce1597c006c5bb9f2497e07441bf064b81003ef8a file diff --git a/support/testing/tests/download/br2-external/git-extra-download/package/main-fails/main-fails.mk b/support/testing/tests/download/br2-external/git-extra-download/package/main-fails/main-fails.mk new file mode 100644 index 0000000000..022bb37cbb --- /dev/null +++ b/support/testing/tests/download/br2-external/git-extra-download/package/main-fails/main-fails.mk @@ -0,0 +1,12 @@ +################################################################################ +# +# main-fails +# +################################################################################ + +MAIN_FAILS_VERSION = a238b1dfcd825d47d834af3c5223417c8411d90d +MAIN_FAILS_SITE = git://localhost:$(GITREMOTE_PORT_NUMBER)/notfound.git +MAIN_FAILS_EXTRA_DOWNLOADS = http://localhost:$(HTTP_SERVER_PORT_NUMBER)/extra +MAIN_FAILS_LICENSE_FILES = file + +$(eval $(generic-package)) diff --git a/support/testing/tests/download/br2-external/git-extra-download/package/ok/ok.hash b/support/testing/tests/download/br2-external/git-extra-download/package/ok/ok.hash new file mode 100644 index 0000000000..366940754b --- /dev/null +++ b/support/testing/tests/download/br2-external/git-extra-download/package/ok/ok.hash @@ -0,0 +1,3 @@ +sha256 737b4fd21506dbaa34cedc93c53c1ebb1f950db2c7644572bb006ae9297961da ok-a238b1dfcd825d47d834af3c5223417c8411d90d.tar.gz +sha256 b9e68e1bea3e5b19ca6b2f98b73a54b73daafaa250484902e09982e07a12e733 extra +sha256 da68f54607d5f5644954096ce1597c006c5bb9f2497e07441bf064b81003ef8a file diff --git a/support/testing/tests/download/br2-external/git-extra-download/package/ok/ok.mk b/support/testing/tests/download/br2-external/git-extra-download/package/ok/ok.mk new file mode 100644 index 0000000000..ce102cb0de --- /dev/null +++ b/support/testing/tests/download/br2-external/git-extra-download/package/ok/ok.mk @@ -0,0 +1,12 @@ +################################################################################ +# +# ok +# +################################################################################ + +OK_VERSION = a238b1dfcd825d47d834af3c5223417c8411d90d +OK_SITE = git://localhost:$(GITREMOTE_PORT_NUMBER)/repo.git +OK_EXTRA_DOWNLOADS = http://localhost:$(HTTP_SERVER_PORT_NUMBER)/extra +OK_LICENSE_FILES = file + +$(eval $(generic-package)) diff --git a/support/testing/tests/download/gitremote.py b/support/testing/tests/download/gitremote.py index 60bc49fbf8..9766b19ce0 100644 --- a/support/testing/tests/download/gitremote.py +++ b/support/testing/tests/download/gitremote.py @@ -1,44 +1,15 @@ -# subprocess does not kill the child daemon when a test case fails by raising -# an exception. So use pexpect instead. -import pexpect - -import infra +from infra.server import Server GIT_REMOTE_PORT_INITIAL = 9418 GIT_REMOTE_PORT_LAST = GIT_REMOTE_PORT_INITIAL + 99 -class GitRemote(object): +class GitRemote(Server): def __init__(self, builddir, serveddir, logtofile): - """ - Start a local git server. - - In order to support test cases in parallel, select the port the - server will listen to in runtime. Since there is no reliable way - to allocate the port prior to starting the server (another - process in the host machine can use the port between it is - selected from a list and it is really allocated to the server) - try to start the server in a port and in the case it is already - in use, try the next one in the allowed range. - """ - self.daemon = None - self.port = None - self.logfile = infra.open_log_file(builddir, "gitremote", logtofile) - daemon_cmd = ["git", "daemon", "--reuseaddr", "--verbose", "--listen=localhost", "--export-all", "--base-path={}".format(serveddir)] - for port in range(GIT_REMOTE_PORT_INITIAL, GIT_REMOTE_PORT_LAST + 1): - cmd = daemon_cmd + ["--port={port}".format(port=port)] - self.logfile.write("> starting git remote with '{}'\n".format(" ".join(cmd))) - self.daemon = pexpect.spawn(cmd[0], cmd[1:], logfile=self.logfile) - ret = self.daemon.expect(["Ready to rumble", - "Address already in use"]) - if ret == 0: - self.port = port - return - raise SystemError("Could not find a free port to run git remote") - - def stop(self): - if self.daemon is None: - return - self.daemon.terminate(force=True) + super(GitRemote, self).__init__( + builddir, serveddir, logtofile, + daemon_cmd, "--port={port}", GIT_REMOTE_PORT_INITIAL, GIT_REMOTE_PORT_LAST, + ["Ready to rumble"], + ["Address already in use"]) diff --git a/support/testing/tests/download/http-server/extra b/support/testing/tests/download/http-server/extra new file mode 100644 index 0000000000..8e27be7d61 --- /dev/null +++ b/support/testing/tests/download/http-server/extra @@ -0,0 +1 @@ +text diff --git a/support/testing/tests/download/httpserver.py b/support/testing/tests/download/httpserver.py new file mode 100644 index 0000000000..9f4f947304 --- /dev/null +++ b/support/testing/tests/download/httpserver.py @@ -0,0 +1,14 @@ +from infra.server import Server + +HTTP_SERVER_PORT_INITIAL = 8000 +HTTP_SERVER_PORT_LAST = HTTP_SERVER_PORT_INITIAL + 99 + + +class HttpServer(Server): + def __init__(self, builddir, serveddir, logtofile): + daemon_cmd = ["python", "-m", "SimpleHTTPServer"] + super(HttpServer, self).__init__( + builddir, serveddir, logtofile, + daemon_cmd, "{port}", HTTP_SERVER_PORT_INITIAL, HTTP_SERVER_PORT_LAST, + ["Serving HTTP"], + ["Address already in use"]) diff --git a/support/testing/tests/download/test_git.py b/support/testing/tests/download/test_git.py index 9fca2bb693..a06ce8bc50 100644 --- a/support/testing/tests/download/test_git.py +++ b/support/testing/tests/download/test_git.py @@ -3,6 +3,7 @@ import shutil import infra from gitremote import GitRemote +from httpserver import HttpServer class GitTestBase(infra.basetest.BRTest): @@ -12,13 +13,19 @@ class GitTestBase(infra.basetest.BRTest): """ gitremotedir = infra.filepath("tests/download/git-remote") gitremote = None + httpserverdir = None + httpserver = None def setUp(self): super(GitTestBase, self).setUp() self.gitremote = GitRemote(self.builddir, self.gitremotedir, self.logtofile) + if self.httpserverdir: + self.httpserver = HttpServer(self.builddir, self.httpserverdir, self.logtofile) def tearDown(self): self.show_msg("Cleaning up") + if self.httpserver: + self.httpserver.stop() if self.gitremote: self.gitremote.stop() if self.b and not self.keepbuilds: @@ -42,11 +49,25 @@ class GitTestBase(infra.basetest.BRTest): shutil.rmtree(dl_dir) env = {"BR2_DL_DIR": dl_dir, "GITREMOTE_PORT_NUMBER": str(self.gitremote.port)} + if self.httpserver: + env["HTTP_SERVER_PORT_NUMBER"] = str(self.httpserver.port) self.b.build(["{}-dirclean".format(package), "{}-legal-info".format(package)], env) +class TestGitExtraDownload(GitTestBase): + br2_external = [infra.filepath("tests/download/br2-external/git-extra-download")] + httpserverdir = infra.filepath("tests/download/http-server") + + def test_run(self): + with self.assertRaises(SystemError): + self.check_download("extra-fails") + with self.assertRaises(SystemError): + self.check_download("main-fails") + self.check_download("ok") + + class TestGitHash(GitTestBase): br2_external = [infra.filepath("tests/download/br2-external/git-hash")] -- 2.14.1