1import os
2import subprocess
3import sys
4import hashlib
5import shutil
6
7def runProcess(cmd):
8	#print " ".join(cmd)
9	process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
10	(stdout, stderr) = process.communicate()
11	if not isinstance(stdout, str): # python 3
12		stdout = stdout.decode('latin-1')
13	if not isinstance(stderr, str): # python 3
14		stderr = stderr.decode('latin-1')
15	#if stderr:
16	#	print stderr
17	return process.returncode, stdout, stderr
18
19def compareInfo(info1, info2):
20	lines1 = info1.splitlines()
21	lines2 = info2.splitlines()
22	if not len(lines1) == len(lines2):
23		return False
24
25	mismatch = False
26	for i in range(len(lines1)):
27		if lines1[i].startswith("chdman - ") and lines2[i].startswith("chdman - "):
28			continue
29		if lines1[i].startswith("Input file:") and lines2[i].startswith("Input file:"):
30			continue
31		if not lines1[i] == lines2[i]:
32			mismatch = True
33			print(lines1[i] + " - " + lines2[i])
34
35	return mismatch == False
36
37def sha1sum(path):
38	if not os.path.exists(path):
39		return ""
40	f = open(path, 'rb')
41	try:
42		sha1 = hashlib.sha1()
43		while True:
44			data = f.read(8192)
45			if data:
46				sha1.update(data)
47			else:
48				break
49	finally:
50		f.close()
51	return sha1.hexdigest()
52
53def extractcdAndCompare(type):
54	global failure
55	extractFileDir = os.path.join(tempFilePath, type + "_output")
56	if not os.path.exists(extractFileDir):
57		os.makedirs(extractFileDir)
58	extractFileBase = os.path.join(extractFileDir, "extract")
59	extractFile = extractFileBase + "." + type
60	extractFileBin = extractFileBase + ".bin"
61
62	exitcode, stdout, stderr = runProcess([chdmanBin, "extractcd", "-f", "-i", outFile, "-o", extractFile])
63	if not exitcode == 0:
64		print(d + " - extractcd (" + type + ") failed with " + str(exitcode) + " (" + stderr + ")")
65		failure = True
66
67	sha1_extract = sha1sum(extractFile)
68	sha1_extract_bin = sha1sum(extractFileBin)
69
70	extractFileDir = os.path.join(tempFilePath, type + "_temp")
71	if not os.path.exists(extractFileDir):
72		os.makedirs(extractFileDir)
73	extractFileBase = os.path.join(extractFileDir, "extract")
74	extractFile = extractFileBase + "." + type
75	extractFileBin = extractFileBase + ".bin"
76
77	exitcode, stdout, stderr = runProcess([chdmanBin, "extractcd", "-f", "-i", tempFile, "-o", extractFile])
78	if not exitcode == 0:
79		print(d + " - extractcd (" + type + ") failed with " + str(exitcode) + " (" + stderr + ")")
80		failure = True
81
82	sha1_extract_2 = sha1sum(extractFile)
83	sha1_extract_bin_2 = sha1sum(extractFileBin)
84
85	if not sha1_extract == sha1_extract_2:
86		print("expected: " + sha1_extract + " found: " + sha1_extract_2)
87		print(d + " - SHA1 mismatch (extractcd - " + type + " - toc)")
88		failure = True
89
90	if not sha1_extract_bin == sha1_extract_bin_2:
91		print("expected: " + sha1_extract_bin + " found: " + sha1_extract_bin_2)
92		print(d + " - SHA1 mismatch (extractcd - " + type + " - bin)")
93		failure = True
94
95def extractAndCompare(command, ext):
96	global failure
97	extractFileDir = os.path.join(tempFilePath, ext + "_output")
98	if not os.path.exists(extractFileDir):
99		os.makedirs(extractFileDir)
100	extractFileBase = os.path.join(extractFileDir, "extract")
101	extractFile = extractFileBase + "." + ext
102
103	exitcode, stdout, stderr = runProcess([chdmanBin, command, "-f", "-i", outFile, "-o", extractFile])
104	if not exitcode == 0:
105		print(d + " - " + command + " (" + ext + ") failed with " + str(exitcode) + " (" + stderr + ")")
106		failure = True
107
108	sha1_extract = sha1sum(extractFile)
109
110	extractFileDir = os.path.join(tempFilePath, ext + "_temp")
111	if not os.path.exists(extractFileDir):
112		os.makedirs(extractFileDir)
113	extractFileBase = os.path.join(extractFileDir, "extract")
114	extractFile = extractFileBase + "." + ext
115
116	exitcode, stdout, stderr = runProcess([chdmanBin, command, "-f", "-i", tempFile, "-o", extractFile])
117	if not exitcode == 0:
118		print(d + " - " + command + " (" + ext + ") failed with " + str(exitcode) + " (" + stderr + ")")
119		failure = True
120
121	sha1_extract_2 = sha1sum(extractFile)
122
123	if not sha1_extract == sha1_extract_2:
124		print("expected: " + sha1_extract + " found: " + sha1_extract_2)
125		print(d + " - SHA1 mismatch (" + command + " - " + ext + ")")
126		failure = True
127
128currentDirectory = os.path.dirname(os.path.realpath(__file__))
129inputPath = os.path.join(currentDirectory, 'input')
130outputPath = os.path.join(currentDirectory, "output")
131tempPath = os.path.join(currentDirectory, "temp")
132if os.name == 'nt':
133	chdmanBin = os.path.normpath(os.path.join(currentDirectory, "..", "..", "chdman.exe"))
134else:
135	chdmanBin = os.path.normpath(os.path.join(currentDirectory, "..", "..", "chdman"))
136
137if not os.path.exists(chdmanBin):
138	sys.stderr.write(chdmanBin + " does not exist\n")
139	sys.exit(1)
140
141if not os.path.exists(inputPath):
142	sys.stderr.write(inputPath + " does not exist\n")
143	sys.exit(1)
144
145if not os.path.exists(outputPath):
146	sys.stderr.write(outputPath + " does not exist\n")
147	sys.exit(1)
148
149if os.path.exists(tempPath):
150	shutil.rmtree(tempPath)
151
152failure = False
153
154for root, dirs, files in os.walk(inputPath):
155	for d in dirs:
156		if d.startswith("."):
157			continue
158
159		command = ext = d.split("_", 2)[0]
160		inFile = os.path.join(root, d, "in")
161		# TODO: make this better
162		outFile = os.path.join(root, d, "out.chd").replace("input", "output")
163		tempFilePath = os.path.join(tempPath, d)
164		tempFile = os.path.join(tempFilePath, "out.chd")
165		inParams = inFile + ".params"
166		params = []
167		if os.path.exists(inParams):
168			f = open(inParams, 'r')
169			paramsstr = f.read()
170			f.close()
171			params = paramsstr.split(" ")
172		if not os.path.exists(tempFilePath):
173			os.makedirs(tempFilePath)
174		if command == "createcd":
175			ext = d.split("_", 2)[1]
176			inFile += "." + ext
177		elif command == "createhd":
178			ext = d.split("_", 2)[1]
179			inFile += "." + ext
180		elif command == "createld":
181			ext = d.split("_", 2)[1]
182			inFile += "." + ext
183		elif command == "copy":
184			inFile += ".chd"
185		else:
186			print("unsupported mode '%s'" % command)
187			continue
188		if os.path.exists(inFile):
189			cmd = [chdmanBin, command, "-f", "-i", inFile, "-o", tempFile] + params
190		else:
191			cmd = [chdmanBin, command, "-f", "-o", tempFile] + params
192
193		exitcode, stdout, stderr = runProcess(cmd)
194		if not exitcode == 0:
195			print(d + " - command failed with " + str(exitcode) + " (" + stderr + ")")
196			failure = True
197
198		# verify
199		exitcode, stdout, stderr = runProcess([chdmanBin, "verify", "-i", tempFile])
200		if not exitcode == 0:
201			print(d + " - verify failed with " + str(exitcode) + " (" + stderr + ")")
202			failure = True
203
204		# compare info
205		# TODO: store expected output of reference file as well and compare
206		exitcode, info1, stderr = runProcess([chdmanBin, "info", "-v", "-i", tempFile])
207		if not exitcode == 0:
208			print(d + " - info (temp) failed with " + str(exitcode) + " (" + stderr + ")")
209			failure = True
210		exitcode, info2, stderr = runProcess([chdmanBin, "info", "-v", "-i", outFile])
211		if not exitcode == 0:
212			print(d + " - info (output) failed with " + str(exitcode) + " (" + stderr + ")")
213			failure = True
214		if not compareInfo(info1, info2):
215			print(d + " - info output differs")
216			failure = True
217
218		# extract and compare
219		if command == "createcd":
220			extractcdAndCompare("toc")
221			extractcdAndCompare("cue")
222		elif command == "createhd":
223			extractAndCompare("extracthd", "raw")
224		elif command == "createld":
225			extractAndCompare("extractld", "avi")
226		# TODO: add extraction for "copy" as well
227
228		# compare SHA1 of output files
229		sha1_out = sha1sum(outFile)
230		sha1_temp = sha1sum(tempFile)
231		if not sha1_out == sha1_temp:
232			print("expected: " + sha1_out + " found: " + sha1_temp)
233			print(d + " - SHA1 mismatch (output file)")
234			failure = True
235
236if not failure:
237	print("All tests finished successfully")
238