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

This commit is contained in:
HelloZeroNet 2015-09-20 22:35:45 +02:00
parent 6a153a48d5
commit 9ac8f7f63c
12 changed files with 89 additions and 34 deletions

View File

@ -1,6 +1,10 @@
language: python
cache: pip
python:
- "2.7"
os:
- linux
- osx
install:
- pip install -r requirements.txt
script:

View File

@ -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

View File

@ -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()

View File

@ -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(" "))

View File

@ -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")

View File

@ -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"

View File

@ -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()

View File

@ -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")

View File

@ -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:

View File

@ -1,4 +1,5 @@
[pytest]
python_files = Test*.py
addopts = -rsxX -v
markers =
webtest: mark a test as a webtest.

View File

@ -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 """
<h1>%s</h1>
<h2>%s</h3>
<h3>Please <a href="https://github.com/HelloZeroNet/ZeroNet/issues" target="_blank">report it</a> if you think this an error.</h3>
<h4>Details:</h4>
<pre>%s</pre>
<style>
* { font-family: Consolas, Monospace; color: #333 }
pre { padding: 10px; background-color: #EEE }
</style>
""" % (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 """
<style>
* { font-family: Consolas, Monospace; color: #333 }
pre { padding: 10px; background-color: #EEE }
</style>
<h1>%s</h1>
<h2>%s</h3>
<h3>Please <a href="https://github.com/HelloZeroNet/ZeroNet/issues" target="_blank">report it</a> if you think this an error.</h3>
<h4>Details:</h4>
<pre>%s</pre>
""" % (title, message, json.dumps(details, indent=4, sort_keys=True))
else:
return """
<h1>%s</h1>
<h2>%s</h3>
""" % (title, message)
# - Reload for eaiser developing -

View File

@ -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: