From 9ac8f7f63ce2cfb93797e54603ca137a87bf823a Mon Sep 17 00:00:00 2001 From: HelloZeroNet Date: Sun, 20 Sep 2015 22:35:45 +0200 Subject: [PATCH] Rev426, Fix for nonce error on bigsites asking, Dont display error details on 404 error, Dont log Websocket close errors, Add travis pip caching and osx test, Add build status to readme, Test for site files after cloning, Test for json to db mapping, Test site deleteFiles command, Test user certificate and auth address generation, Exclude debug lines from coverage, Dont run webtests every time --- .travis.yml | 4 ++++ README.md | 2 +- src/Config.py | 2 +- src/Test/TestConfig.py | 2 +- src/Test/TestSite.py | 10 ++++++--- src/Test/TestUser.py | 35 +++++++++++++++++++++++++---- src/Test/TestWeb.py | 1 + src/Test/conftest.py | 1 + src/Test/coverage.ini | 11 +++++++++ src/Test/pytest.ini | 3 ++- src/Ui/UiRequest.py | 51 ++++++++++++++++++++++++------------------ src/Ui/UiWebsocket.py | 1 - 12 files changed, 89 insertions(+), 34 deletions(-) diff --git a/.travis.yml b/.travis.yml index 00aecc23..64287630 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,10 @@ language: python +cache: pip python: - "2.7" +os: + - linux + - osx install: - pip install -r requirements.txt script: diff --git a/README.md b/README.md index 23494899..dcc554d1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ZeroNet +# ZeroNet [![Build Status](https://travis-ci.org/HelloZeroNet/ZeroNet.svg?branch=master)](https://travis-ci.org/HelloZeroNet/ZeroNet) Decentralized websites using Bitcoin crypto and the BitTorrent network - http://zeronet.io diff --git a/src/Config.py b/src/Config.py index e3873ee9..1216089d 100644 --- a/src/Config.py +++ b/src/Config.py @@ -8,7 +8,7 @@ class Config(object): def __init__(self, argv): self.version = "0.3.2" - self.rev = 423 + self.rev = 426 self.argv = argv self.action = None self.createParser() diff --git a/src/Test/TestConfig.py b/src/Test/TestConfig.py index d33f0161..24084392 100644 --- a/src/Test/TestConfig.py +++ b/src/Test/TestConfig.py @@ -4,7 +4,7 @@ import Config @pytest.mark.usefixtures("resetSettings") -class TestUser: +class TestConfig: def testParse(self): # Defaults config_test = Config.Config("zeronet.py".split(" ")) diff --git a/src/Test/TestSite.py b/src/Test/TestSite.py index 06e482d2..ffa951e9 100644 --- a/src/Test/TestSite.py +++ b/src/Test/TestSite.py @@ -25,6 +25,8 @@ class TestSite: assert new_site.storage.isFile("index.html") assert new_site.storage.isFile("data/users/content.json") assert new_site.storage.isFile("data/zeroblog.db") + assert new_site.storage.verifyFiles() == [] # No bad files allowed + assert new_site.storage.query("SELECT * FROM keyvalue WHERE key = 'title'").fetchone()["value"] == "MyZeroBlog" # Test re-cloning (updating) @@ -41,6 +43,9 @@ class TestSite: changed_data["title"] = "UpdateTest" new_site.storage.writeJson("data/data.json", changed_data) + # The update should be reflected to database + assert new_site.storage.query("SELECT * FROM keyvalue WHERE key = 'title'").fetchone()["value"] == "UpdateTest" + # Re-clone the site site.clone("159EGD5srUsMP97UpcLy8AtKQbQLK2AbbL") @@ -49,6 +54,5 @@ class TestSite: assert new_site.storage.read("index.html") != "this will be overwritten" # Delete created files - if os.path.isdir("src/Test/testdata/159EGD5srUsMP97UpcLy8AtKQbQLK2AbbL"): - new_site.storage.closeDb() - shutil.rmtree("src/Test/testdata/159EGD5srUsMP97UpcLy8AtKQbQLK2AbbL") + new_site.storage.deleteFiles() + assert not os.path.isdir("src/Test/testdata/159EGD5srUsMP97UpcLy8AtKQbQLK2AbbL") diff --git a/src/Test/TestUser.py b/src/Test/TestUser.py index f3cfe3bf..1fcdd1b7 100644 --- a/src/Test/TestUser.py +++ b/src/Test/TestUser.py @@ -5,14 +5,14 @@ from Crypt import CryptBitcoin @pytest.mark.usefixtures("resetSettings") class TestUser: - def testNewsite(self, user): - user.sites = {} # Reset user data + def testAddress(self, user): assert user.master_address == "15E5rhcAUD69WbiYsYARh4YHJ4sLm2JEyc" address_index = 1458664252141532163166741013621928587528255888800826689784628722366466547364755811L assert user.getAddressAuthIndex("15E5rhcAUD69WbiYsYARh4YHJ4sLm2JEyc") == address_index - # Re-generate privatekey based on address_index - address, address_index, site_data = user.getNewSiteData() + # Re-generate privatekey based on address_index + def testNewSite(self, user): + address, address_index, site_data = user.getNewSiteData() # Create a new random site assert CryptBitcoin.hdPrivatekey(user.master_seed, address_index) == site_data["privatekey"] user.sites = {} # Reset user data @@ -21,3 +21,30 @@ class TestUser: assert user.getSiteData(address)["auth_address"] != address # Re-generate auth_privatekey for site assert user.getSiteData(address)["auth_privatekey"] == site_data["auth_privatekey"] + + def testAuthAddress(self, user): + # Auth address without Cert + auth_address = user.getAuthAddress("1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr") + assert auth_address == "1MyJgYQjeEkR9QD66nkfJc9zqi9uUy5Lr2" + auth_privatekey = user.getAuthPrivatekey("1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr") + assert CryptBitcoin.privatekeyToAddress(auth_privatekey) == auth_address + + def testCert(self, user): + cert_auth_address = user.getAuthAddress("1iD5ZQJMNXu43w1qLB8sfdHVKppVMduGz") # Add site to user's registry + # Add cert + user.addCert(cert_auth_address, "zeroid.bit", "faketype", "fakeuser", "fakesign") + user.setCert("1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr", "zeroid.bit") + + # By using certificate the auth address should be same as the certificate provider + assert user.getAuthAddress("1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr") == cert_auth_address + auth_privatekey = user.getAuthPrivatekey("1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr") + assert CryptBitcoin.privatekeyToAddress(auth_privatekey) == cert_auth_address + + # Test delete site data + assert "1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr" in user.sites + user.deleteSiteData("1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr") + assert "1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr" not in user.sites + + # Re-create add site should generate normal, unique auth_address + assert not user.getAuthAddress("1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr") == cert_auth_address + assert user.getAuthAddress("1EU1tbG9oC1A8jz2ouVwGZyQ5asrNsE4Vr") == "1MyJgYQjeEkR9QD66nkfJc9zqi9uUy5Lr2" diff --git a/src/Test/TestWeb.py b/src/Test/TestWeb.py index 4960ca33..e637fde4 100644 --- a/src/Test/TestWeb.py +++ b/src/Test/TestWeb.py @@ -22,6 +22,7 @@ class WaitForPageLoad(object): @pytest.mark.usefixtures("resetSettings") +@pytest.mark.webtest class TestWeb: def testFileSecurity(self, site_url): assert "Forbidden" in urllib.urlopen("%s/media/./sites.json" % site_url).read() diff --git a/src/Test/conftest.py b/src/Test/conftest.py index 5c222fef..3e7f5b4a 100644 --- a/src/Test/conftest.py +++ b/src/Test/conftest.py @@ -50,6 +50,7 @@ def site(): @pytest.fixture(scope="session") def user(): user = UserManager.user_manager.get() + user.sites = {} # Reset user data return user @pytest.fixture(scope="session") diff --git a/src/Test/coverage.ini b/src/Test/coverage.ini index 5b69dc21..28732e91 100644 --- a/src/Test/coverage.ini +++ b/src/Test/coverage.ini @@ -3,4 +3,15 @@ branch = True omit = src/lib/* src/Test/* + [report] +exclude_lines = + pragma: no cover + + if __name__ == .__main__.: + + if config.debug: + + if config.debug_socket: + + if self.logging: \ No newline at end of file diff --git a/src/Test/pytest.ini b/src/Test/pytest.ini index 6e9e4712..081cf778 100644 --- a/src/Test/pytest.ini +++ b/src/Test/pytest.ini @@ -1,4 +1,5 @@ [pytest] python_files = Test*.py addopts = -rsxX -v - +markers = + webtest: mark a test as a webtest. \ No newline at end of file diff --git a/src/Ui/UiRequest.py b/src/Ui/UiRequest.py index 54757cb1..decd05f5 100644 --- a/src/Ui/UiRequest.py +++ b/src/Ui/UiRequest.py @@ -152,7 +152,7 @@ class UiRequest(object): if status == 200 and cacheable_type: # Cache Css, Js, Image files for 10min headers.append(("Cache-Control", "public, max-age=600")) # Cache 10 min - else: # Images, Css, Js + else: headers.append(("Cache-Control", "no-cache, no-store, private, must-revalidate, max-age=0")) # No caching at all headers.append(("Content-Type", content_type)) for extra_header in extra_headers: @@ -327,16 +327,17 @@ class UiRequest(object): from Debug import DebugMedia DebugMedia.merge(file_path) if os.path.isfile(file_path): # File exits - # self.sendHeader(content_type=self.getContentType(file_path)) # ?? Get Exception without this return self.actionFile(file_path) else: # File not exits, try to download site = SiteManager.site_manager.need(address, all_file=False) result = site.needFile(match.group("inner_path"), priority=1) # Wait until file downloads if result: - # self.sendHeader(content_type=self.getContentType(file_path)) return self.actionFile(file_path) else: self.log.debug("File not found: %s" % match.group("inner_path")) + # Site larger than allowed, re-add wrapper nonce to allow reload + if site.settings.get("size", 0) > site.getSizeLimit()*1024*1024: + self.server.wrapper_nonces.append(self.get.get("wrapper_nonce")) return self.error404(match.group("inner_path")) else: # Bad url @@ -460,7 +461,7 @@ class UiRequest(object): # Send file not found error def error404(self, path=""): self.sendHeader(404) - return self.formatError("Not Found", path.encode("utf8")) + return self.formatError("Not Found", path.encode("utf8"), details=False) # Internal server error def error500(self, message=":("): @@ -471,24 +472,30 @@ class UiRequest(object): import sys import gevent - details = {key: val for key, val in self.env.items() if hasattr(val, "endswith") and "COOKIE" not in key} - details["version_zeronet"] = "%s r%s" % (config.version, config.rev) - details["version_python"] = sys.version - details["version_gevent"] = gevent.__version__ - details["plugins"] = PluginManager.plugin_manager.plugin_names - arguments = {key: val for key, val in vars(config.arguments).items() if "password" not in key} - details["arguments"] = arguments - return """ -

%s

-

%s

-

Please report it if you think this an error.

-

Details:

-
%s
- - """ % (title, message, json.dumps(details, indent=4, sort_keys=True)) + if details: + details = {key: val for key, val in self.env.items() if hasattr(val, "endswith") and "COOKIE" not in key} + details["version_zeronet"] = "%s r%s" % (config.version, config.rev) + details["version_python"] = sys.version + details["version_gevent"] = gevent.__version__ + details["plugins"] = PluginManager.plugin_manager.plugin_names + arguments = {key: val for key, val in vars(config.arguments).items() if "password" not in key} + details["arguments"] = arguments + return """ + +

%s

+

%s

+

Please report it if you think this an error.

+

Details:

+
%s
+ """ % (title, message, json.dumps(details, indent=4, sort_keys=True)) + else: + return """ +

%s

+

%s

+ """ % (title, message) # - Reload for eaiser developing - diff --git a/src/Ui/UiWebsocket.py b/src/Ui/UiWebsocket.py index f58bdb53..c419d1b3 100644 --- a/src/Ui/UiWebsocket.py +++ b/src/Ui/UiWebsocket.py @@ -58,7 +58,6 @@ class UiWebsocket(object): try: message = ws.receive() except Exception, err: - self.log.error("WebSocket receive error: %s" % err) return "Bye." # Close connection if message: