diff options
Diffstat (limited to 'WebKitTools/TestResultServer/handlers')
-rw-r--r-- | WebKitTools/TestResultServer/handlers/dashboardhandler.py | 5 | ||||
-rw-r--r-- | WebKitTools/TestResultServer/handlers/menu.py | 5 | ||||
-rw-r--r-- | WebKitTools/TestResultServer/handlers/testfilehandler.py | 126 |
3 files changed, 58 insertions, 78 deletions
diff --git a/WebKitTools/TestResultServer/handlers/dashboardhandler.py b/WebKitTools/TestResultServer/handlers/dashboardhandler.py index 45bc471..587d737 100644 --- a/WebKitTools/TestResultServer/handlers/dashboardhandler.py +++ b/WebKitTools/TestResultServer/handlers/dashboardhandler.py @@ -3,7 +3,7 @@ # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above @@ -13,7 +13,7 @@ # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -38,6 +38,7 @@ from model.dashboardfile import DashboardFile PARAM_FILE = "file" + def get_content_type(filename): return mimetypes.guess_type(filename)[0] or "application/octet-stream" diff --git a/WebKitTools/TestResultServer/handlers/menu.py b/WebKitTools/TestResultServer/handlers/menu.py index ad2599d..f2f3855 100644 --- a/WebKitTools/TestResultServer/handlers/menu.py +++ b/WebKitTools/TestResultServer/handlers/menu.py @@ -3,7 +3,7 @@ # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above @@ -13,7 +13,7 @@ # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -61,4 +61,3 @@ class Menu(webapp.RequestHandler): self.response.out.write( template.render("templates/menu.html", template_values)) - diff --git a/WebKitTools/TestResultServer/handlers/testfilehandler.py b/WebKitTools/TestResultServer/handlers/testfilehandler.py index 972b606..97953e7 100644 --- a/WebKitTools/TestResultServer/handlers/testfilehandler.py +++ b/WebKitTools/TestResultServer/handlers/testfilehandler.py @@ -3,7 +3,7 @@ # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: -# +# # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above @@ -13,7 +13,7 @@ # * Neither the name of Google Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. -# +# # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -30,11 +30,10 @@ import logging import urllib from google.appengine.api import users -from google.appengine.ext import blobstore from google.appengine.ext import webapp -from google.appengine.ext.webapp import blobstore_handlers from google.appengine.ext.webapp import template +from model.jsonresults import JsonResults from model.testfile import TestFile PARAM_BUILDER = "builder" @@ -43,10 +42,11 @@ PARAM_FILE = "file" PARAM_NAME = "name" PARAM_KEY = "key" PARAM_TEST_TYPE = "testtype" +PARAM_INCREMENTAL = "incremental" class DeleteFile(webapp.RequestHandler): - """Delete test file for a given builder and name from datastore (metadata) and blobstore (file data).""" + """Delete test file for a given builder and name from datastore.""" def get(self): key = self.request.get(PARAM_KEY) @@ -55,7 +55,7 @@ class DeleteFile(webapp.RequestHandler): name = self.request.get(PARAM_NAME) logging.debug( - "Deleting File, builder: %s, test_type: %s, name: %s, blob key: %s.", + "Deleting File, builder: %s, test_type: %s, name: %s, key: %s.", builder, test_type, name, key) TestFile.delete_file(key, builder, test_type, name, 100) @@ -65,7 +65,7 @@ class DeleteFile(webapp.RequestHandler): % (builder, test_type, name)) -class GetFile(blobstore_handlers.BlobstoreDownloadHandler): +class GetFile(webapp.RequestHandler): """Get file content or list of files for given builder and name.""" def _get_file_list(self, builder, test_type, name): @@ -77,7 +77,8 @@ class GetFile(blobstore_handlers.BlobstoreDownloadHandler): name: file name """ - files = TestFile.get_files(builder, test_type, name, 100) + files = TestFile.get_files( + builder, test_type, name, load_data=False, limit=100) if not files: logging.info("File not found, builder: %s, test_type: %s, name: %s.", builder, test_type, name) @@ -103,16 +104,15 @@ class GetFile(blobstore_handlers.BlobstoreDownloadHandler): name: file name """ - files = TestFile.get_files(builder, test_type, name, 1) + files = TestFile.get_files( + builder, test_type, name, load_data=True, limit=1) if not files: logging.info("File not found, builder: %s, test_type: %s, name: %s.", builder, test_type, name) return - blob_key = files[0].blob_key - blob_info = blobstore.get(blob_key) - if blob_info: - self.send_blob(blob_info, "text/plain") + self.response.headers["Content-Type"] = "text/plain; charset=utf-8" + self.response.out.write(files[0].data) def get(self): builder = self.request.get(PARAM_BUILDER) @@ -133,89 +133,69 @@ class GetFile(blobstore_handlers.BlobstoreDownloadHandler): return self._get_file_content(builder, test_type, name) -class GetUploadUrl(webapp.RequestHandler): - """Get an url for uploading file to blobstore. A special url is required for each blobsotre upload.""" - - def get(self): - upload_url = blobstore.create_upload_url("/testfile/upload") - logging.info("Getting upload url: %s.", upload_url) - self.response.out.write(upload_url) - - -class Upload(blobstore_handlers.BlobstoreUploadHandler): - """Upload file to blobstore.""" +class Upload(webapp.RequestHandler): + """Upload test results file to datastore.""" def post(self): - uploaded_files = self.get_uploads("file") - if not uploaded_files: - return self._upload_done([("Missing upload file field.")]) + file_params = self.request.POST.getall(PARAM_FILE) + if not file_params: + self.response.out.write("FAIL: missing upload file field.") + return builder = self.request.get(PARAM_BUILDER) if not builder: - for blob_info in uploaded_files: - blob_info.delete() - - return self._upload_done([("Missing builder parameter in upload request.")]) + self.response.out.write("FAIL: missing builder parameter.") + return test_type = self.request.get(PARAM_TEST_TYPE) + incremental = self.request.get(PARAM_INCREMENTAL) logging.debug( "Processing upload request, builder: %s, test_type: %s.", builder, test_type) + # There are two possible types of each file_params in the request: + # one file item or a list of file items. + # Normalize file_params to a file item list. + files = [] + logging.debug("test: %s, type:%s", file_params, type(file_params)) + for item in file_params: + if not isinstance(item, list) and not isinstance(item, tuple): + item = [item] + files.extend(item) + errors = [] - for blob_info in uploaded_files: - tf = TestFile.update_file(builder, test_type, blob_info) - if not tf: + for file in files: + filename = file.filename.lower() + if ((incremental and filename == "results.json") or + (filename == "incremental_results.json")): + # Merge incremental json results. + saved_file = JsonResults.update(builder, test_type, file.value) + else: + saved_file = TestFile.update( + builder, test_type, file.filename, file.value) + + if not saved_file: errors.append( "Upload failed, builder: %s, test_type: %s, name: %s." % - (builder, test_type, blob_info.filename)) - blob_info.delete() - - return self._upload_done(errors) - - def _upload_done(self, errors): - logging.info("upload done.") + (builder, test_type, file.filename)) - error_messages = [] - for error in errors: - logging.info(error) - error_messages.append("error=%s" % urllib.quote(error)) - - if error_messages: - redirect_url = "/uploadfail?%s" % "&".join(error_messages) + if errors: + messages = "FAIL: " + "; ".join(errors) + logging.warning(messages) + self.response.set_status(500, messages) + self.response.out.write("FAIL") else: - redirect_url = "/uploadsuccess" - - logging.info(redirect_url) - # BlobstoreUploadHandler requires redirect at the end. - self.redirect(redirect_url) + self.response.set_status(200) + self.response.out.write("OK") class UploadForm(webapp.RequestHandler): - """Show a form so user can submit a file to blobstore.""" + """Show a form so user can upload a file.""" def get(self): - upload_url = blobstore.create_upload_url("/testfile/upload") template_values = { - "upload_url": upload_url, + "upload_url": "/testfile/upload", } self.response.out.write(template.render("templates/uploadform.html", template_values)) - -class UploadStatus(webapp.RequestHandler): - """Return status of file uploading""" - - def get(self): - logging.debug("Update status") - - if self.request.path == "/uploadsuccess": - self.response.set_status(200) - self.response.out.write("OK") - else: - errors = self.request.params.getall("error") - if errors: - messages = "FAIL: " + "; ".join(errors) - logging.warning(messages) - self.response.set_status(500, messages) - self.response.out.write("FAIL") |