Merge remote branch 'github/topic/regression_testing'

This commit is contained in:
Caleb Deveraux 2010-10-03 22:42:22 -06:00
commit d24b4dc10b
4 changed files with 129 additions and 8 deletions

9
mce.py Normal file → Executable file
View File

@ -1,3 +1,4 @@
#!/usr/bin/env python
import mclevel import mclevel
import sys import sys
import os import os
@ -10,6 +11,8 @@ class BlockMatchError(RuntimeError): pass
class PlayerNotFound(RuntimeError): pass class PlayerNotFound(RuntimeError): pass
class mce(object): class mce(object):
random_seed = os.getenv('MCE_RANDOM_SEED', None)
last_played = os.getenv("MCE_LAST_PLAYED", None)
""" """
Usage: Usage:
@ -369,7 +372,7 @@ class mce(object):
filename = command.pop(0) filename = command.pop(0)
destPoint = self.readPoint(command) destPoint = self.readPoint(command)
importLevel = mclevel.fromFile(filename) importLevel = mclevel.fromFile(filename, last_played=self.last_played, random_seed=self.random_seed)
self.level.copyBlocksFrom(importLevel, importLevel.getWorldBounds(), destPoint); self.level.copyBlocksFrom(importLevel, importLevel.getWorldBounds(), destPoint);
@ -652,7 +655,7 @@ class mce(object):
self.loadWorld(command[0]) self.loadWorld(command[0])
def _reload(self, command): def _reload(self, command):
self.level = mclevel.fromFile(self.filename); self.level = mclevel.fromFile(self.filename, last_played=self.last_played, random_seed=self.random_seed);
def _help(self, command): def _help(self, command):
if len(command): if len(command):
@ -706,7 +709,7 @@ class mce(object):
try: try:
worldNum = int(world) worldNum = int(world)
except ValueError: except ValueError:
self.level = mclevel.fromFile(world) self.level = mclevel.fromFile(world, last_played=self.last_played, random_seed=self.random_seed)
self.filename = self.level.filename self.filename = self.level.filename

View File

@ -582,7 +582,7 @@ class MCLevel(object):
def saveInPlace(self): def saveInPlace(self):
self.saveToFile(self.filename); self.saveToFile(self.filename);
@classmethod @classmethod
def fromFile(cls, filename, loadInfinite=True): def fromFile(cls, filename, loadInfinite=True, random_seed=None, last_played=None):
''' The preferred method for loading Minecraft levels of any type. ''' The preferred method for loading Minecraft levels of any type.
pass False to loadInfinite if you'd rather not load infdev levels.''' pass False to loadInfinite if you'd rather not load infdev levels.'''
info( "Identifying " + filename ) info( "Identifying " + filename )
@ -599,7 +599,7 @@ class MCLevel(object):
raise; raise;
try: try:
info( "Can't read, attempting to open directory" ) info( "Can't read, attempting to open directory" )
lev = MCInfdevOldLevel(filename=filename) lev = MCInfdevOldLevel(filename=filename, random_seed=random_seed, last_played=last_played)
info( "Detected Alpha world." ) info( "Detected Alpha world." )
return lev; return lev;
except Exception, ex: except Exception, ex:
@ -1499,7 +1499,7 @@ class MCInfdevOldLevel(MCLevel):
def __str__(self): def __str__(self):
return "MCInfdevOldLevel(" + os.path.split(self.worldDir)[1] + ")" return "MCInfdevOldLevel(" + os.path.split(self.worldDir)[1] + ")"
def __init__(self, filename = None, root_tag = None): def __init__(self, filename = None, root_tag = None, random_seed=None, last_played=None):
#pass level.dat's root tag and filename to read an existing level. #pass level.dat's root tag and filename to read an existing level.
#pass only filename to create a new one #pass only filename to create a new one
#filename should be the path to the world dir #filename should be the path to the world dir
@ -1526,8 +1526,13 @@ class MCInfdevOldLevel(MCLevel):
root_tag[Data][SpawnY] = TAG_Int(2) root_tag[Data][SpawnY] = TAG_Int(2)
root_tag[Data][SpawnZ] = TAG_Int(0) root_tag[Data][SpawnZ] = TAG_Int(0)
root_tag[Data]['LastPlayed'] = TAG_Long(long(time.time())) if last_played is None:
root_tag[Data]['RandomSeed'] = TAG_Long(int(random.random() * ((2<<31)))) last_played = time.time()
if random_seed is None:
random_seed = random.random() * ((2<<31))
root_tag[Data]['LastPlayed'] = TAG_Long(long(last_played))
root_tag[Data]['RandomSeed'] = TAG_Long(int(random_seed))
root_tag[Data]['SizeOnDisk'] = TAG_Long(long(1048576)) root_tag[Data]['SizeOnDisk'] = TAG_Long(long(1048576))
root_tag[Data]['Time'] = TAG_Long(1) root_tag[Data]['Time'] = TAG_Long(1)
root_tag[Data]['SnowCovered'] = TAG_Byte(0); root_tag[Data]['SnowCovered'] = TAG_Byte(0);

Binary file not shown.

113
run_regression_test.py Executable file
View File

@ -0,0 +1,113 @@
#!/usr/bin/env python
import tempfile
import sys
import subprocess
import shutil
import os
import mclevel
import hashlib
import contextlib
import gzip
import fnmatch
import tarfile
import zipfile
def generate_file_list(directory):
for dirpath, dirnames, filenames in os.walk(directory):
for filename in filenames:
yield os.path.join(dirpath, filename)
def sha1_file(name, checksum=None):
CHUNKSIZE=1024
if checksum is None:
checksum = hashlib.sha1()
if fnmatch.fnmatch(name, "*.dat"):
opener = gzip.open
else:
opener = open
with contextlib.closing(opener(name, 'rb')) as data:
chunk = data.read(CHUNKSIZE)
while len(chunk) == CHUNKSIZE:
checksum.update(chunk)
chunk = data.read(CHUNKSIZE)
else:
checksum.update(chunk)
return checksum
def calculate_result(directory):
checksum = hashlib.sha1()
for filename in sorted(generate_file_list(directory)):
sha1_file(filename, checksum)
return checksum.hexdigest()
@contextlib.contextmanager
def temporary_directory(prefix='regr'):
name = tempfile.mkdtemp(prefix)
try:
yield name
finally:
shutil.rmtree(name)
@contextlib.contextmanager
def directory_clone(src):
with temporary_directory('regr') as name:
subdir = os.path.join(name, "subdir")
shutil.copytree(src, subdir)
yield subdir
@contextlib.contextmanager
def unzipped_content(src):
with temporary_directory() as dest:
f = zipfile.ZipFile.open(name)
f.extractall(dest)
yield dest
@contextlib.contextmanager
def untared_content(src):
with temporary_directory() as dest:
f = tarfile.TarFile.open(src)
f.extractall(dest)
yield dest
class RegressionError(Exception): pass
def do_test(test_data, result_check, arguments=[]):
"""Run a regression test on the given world.
result_check - sha1 of the recursive tree generated
arguments - arguments to give to mce.py on execution
"""
result_check = result_check.lower()
env = {
'MCE_RANDOM_SEED' : '42',
'MCE_LAST_PLAYED' : '42'
}
with directory_clone(test_data) as directory:
proc = subprocess.Popen([
"./mce.py",
directory] + arguments, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, env=env)
proc.stdin.close()
result = proc.wait()
if os.WIFEXITED(result) and os.WEXITSTATUS(result):
raise RegressionError("Program execution failed!")
checksum = calculate_result(directory).lower()
if checksum != result_check.lower():
raise RegressionError("Checksum mismatch: {0!r} != {1!r}".format(checksum, result_check))
print "[OK]"
def main(argv):
with untared_content("regression_test/alpha.tar.gz") as directory:
test_data = os.path.join(directory, "alpha")
do_test(test_data, 'ca66277d8037fde5aea3a135dd186f91e4bf4bef')
do_test(test_data, '0f4cbb81f7f109cee10606b82f27fb2681a22f50', ['degrief'])
if __name__ == '__main__':
sys.exit(main(sys.argv))