From 64a856f62b603c6fda7926a5d34fdd00ac3d405c Mon Sep 17 00:00:00 2001 From: Ken Dreyer Date: Wed, 9 Nov 2022 10:41:15 -0500 Subject: [PATCH] kojikamid: write buildrequires files as bytes Fix a TypeError when downloading buildrequires files on Python 3. base64.b64decode() returns bytes, so we must open the file for writing in bytes mode, not text mode. Add a unit test that verifies this behavior. --- tests/test_vm/data/koji.png | Bin 0 -> 2118 bytes tests/test_vm/test_kojikamid.py | 65 ++++++++++++++++++++++++++++++++ vm/kojikamid.py | 2 +- 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 tests/test_vm/data/koji.png create mode 100644 tests/test_vm/test_kojikamid.py diff --git a/tests/test_vm/data/koji.png b/tests/test_vm/data/koji.png new file mode 100644 index 0000000000000000000000000000000000000000..2a7b508c18ff5be2e52840cee36de746ae982223 GIT binary patch literal 2118 zcmV-M2)Xx(P) zC=0Dg(Tha(Vl^ryDkyuw2&6PA`ojo~kfK7P!qOzPBBHdSM9DPGiI|ql>1<}2b2@kL z-TD4;`mNi&o9VBw@O}O|d+s^ApZmOgp659TV+{W>p=>LR@vB#_{&-+`c-U+a5eqySxucs&qAyigY=4h+YXpD)8sjaQW z(=0!I7aSZcm&*a*;lqcHEPDL-@wIE$E?v5G+5^glZriqP0H9PVtyZfLdueHDLP7#f z(|G#j7p9vxZvucwB>MdMGjEets|^YY`ts$=-@Hky)eZ~{@RV(BZ4C_#TqMGX%R+mx-XtqO(0*Vk90(b&htvaC|6 z1c1!UOzw_z=gy_4r`vVtB*kjA#>K_?`1mw5G;sB5wc5+e>&=@t4t<9)PDx1tfDIcq z*fcdYH6bA(Mx*gBL*&DU4_#edJmuKfSbu;2MDc_%K6~~o00agGlAk|*{0I#Vt*@`2 z)`;%y?KKz-T#cBUgF!(-0HD+9%x1GhA~}5caB6Dm;>C;YW@}SZQ+auLb8|CAQGR}Y z;o;%Q$;pIJ97$GI{veSLjxnx38>l}dH_^5yvWcspExF>YyTK?qS4)!W;9_wLI0cFCF@BaBxr} zkpMtNMMY3hPj$f_?k;&7C_J{ZAGyTqq13nx_5y z{18GsOu@myf51f3w3n9`0L+;)$8PfH=jW%UrV5E_bab?^uuv|S6Ic-u5xkm6)3mp@ zw-D2U1q%S+-Me=VF|jNg5D)+Wd-m)RCVx>;(Z-D%S(bGat=-+-p`oD!R&H)C_mRb7 zA((jI6Broy2TT~_h=>RP5E`kyz1_{tjYlv-`Sj@%v6i>DH#e{>7K>airzq;%w{P72 z#00#*{Vh(7Mx()CAOXuunXIfVe}Dh5u&{}%XFx!}$&)7mpufNW#fuj9SS$!3 zu~;lT<>KOEzo!F$6DLmSbUNV~yEy+8Vz@M_hrkL0YG10pG`^AG|RFSMe!JfWm%zH zC@x{f#l?|zXJ;pOlSZQf0ES^E+5aqBw1~7AHjUYAW?9zB$;qzoc*gsMNh}r@78VkI zI&*NHSu13+6_+axi$y1J4Y#q*IwB5`tZ;?gy-lSAK;Zd0L90Km}D(6M93Y$J__ zhX(-E*47%0#>rqB9v(&r5f2g>A0KB~RxB2C-9&0Him_TMMg&2Gz`OFjCuJ*&>)0n%$Q-n_a%*hv$L~QDkUEj5D+jlG=wo8 z85tq0qfjUY2L~snD1*V^>grlvUd~m%fBzl;=FgwcBhp#3W+8-hI-Ns)8W13-6o_l_MqCZ6x|^Yhheb#ihtS2;E|1^`m2l$UgN`0-dC`zSL39Bp#*rKAMty{NREEe9Q*RNj# zKwMlLS7|nz-QC>*;N!=S4(&uJAUHVK$H(XV`SS=Nnx-={G8l%D%jNg(-IK{=7~`i; zpN5BrA31WQy1Kfzw^y&%Yc!hT;^NrY*k{k46&DwClZ$I7lGMC-0)VEbCWm%9dh{p& zJb(TiW6Us2Qc@C$!AqAekqvL(z6}Wp;id_pL4=T-o7;s87aUdS%F0RrNJ>iL_388G z%|i%9M@K(?{P@wMM|Ns(Qc{vgBGbK-6h$>RH&1O2CN3{5EadH|s;Y8!c18&K`}^A^CzfS1GBRRg zV<(saSFc_j6B9GZA@LU`()TnqH3>JRr>7GS9y)YL`1Jbq>%@?bX62rqo|!XeR##U~ z`Mw}NK3*=D+Z|L41_L1{iA2KdQ!&Pkjg5r&Jv}|Es;Y!T@WF!zb8>Q~e1|bQIx3Y) zxf3u?Zr{F5ay~jbT8Ml9{{4h(#A5NTUAvwoPMlr!?9FmuH2+ zWD|yA5)%`N2MY=cgmcT5En5g^E^oQGxLmw=ajJI>KQU!zXDbv6y&EPU7RsaA107*qoM6N<$f=}q*0RR91 literal 0 HcmV?d00001 diff --git a/tests/test_vm/test_kojikamid.py b/tests/test_vm/test_kojikamid.py new file mode 100644 index 00000000..ffff1adf --- /dev/null +++ b/tests/test_vm/test_kojikamid.py @@ -0,0 +1,65 @@ +import base64 +import filecmp +import importlib.machinery +import importlib.util +import os +import tempfile +from subprocess import check_call + +VM_TESTS_DIR = os.path.dirname(os.path.abspath(__file__)) +LOGO_FIXTURE = os.path.join(VM_TESTS_DIR, 'data', 'koji.png') +TESTS_DIR = os.path.dirname(VM_TESTS_DIR) +VM_DIR = os.path.join(os.path.dirname(TESTS_DIR), 'vm') + +# Generate the kojikamid file before importing. +tmpfile = tempfile.NamedTemporaryFile(prefix='kojikamid.') +check_call(['bash', 'fix_kojikamid.sh'], cwd=VM_DIR, stdout=tmpfile) +print(tmpfile.name) + +# Dynamically import our temporary kojikamid file. +loader = importlib.machinery.SourceFileLoader('kojikamid', tmpfile.name) +spec = importlib.util.spec_from_loader(loader.name, loader) +kojikamid = importlib.util.module_from_spec(spec) +loader.exec_module(kojikamid) + + +class FakeServer(object): + def getTaskInfo(self): + # Koji's getTaskInfo(..., request=True) returns the task's request + # data. kojivmd strips this down to the second element of that request + # and returns it here: + return ['git://example.com/ceph.git#abc123', + 'ceph-6.1-win-build', + {'repo_id': 2, + 'winspec': 'git://example.com/pkg.git?ceph#def456'}] + + def getFile(self, buildinfo, archiveinfo, offset, length, type): + # Return a base64-encoded static fixture (a PNG image). + offset = int(offset) + length = int(length) + with open(LOGO_FIXTURE, 'rb') as fileobj: + try: + fileobj.seek(offset) + data = fileobj.read(length) + encoded = base64.b64encode(data).decode() + del data + return encoded + finally: + fileobj.close() + + +def test_fetch_file(tmpdir): + server = FakeServer() + build = kojikamid.WindowsBuild(server) + basedir = str(tmpdir) + buildinfo = { + 'name': 'wnbd', + } + fileinfo = { + 'localpath': 'koji.png', + 'checksum_type': 2, # sha256 + 'checksum': 'f78bc62287eec7641a85a7d1c0435c995672e7f46e33de72a82775b1fb16a93f', + } + build.fetchFile(basedir, buildinfo, fileinfo, 'win') + fetched = str(tmpdir.join('koji.png')) + assert filecmp.cmp(fetched, LOGO_FIXTURE) diff --git a/vm/kojikamid.py b/vm/kojikamid.py index f5a7460a..08c9a783 100755 --- a/vm/kojikamid.py +++ b/vm/kojikamid.py @@ -335,7 +335,7 @@ class WindowsBuild(object): raise BuildError('Unknown checksum type %s for %s' % ( # noqa: F821 checksum_type, os.path.basename(fileinfo['localpath']))) - with koji._open_text_file(destpath, 'wt') as destfile: + with open(destpath, 'wb') as destfile: offset = 0 while True: encoded = self.server.getFile(buildinfo, fileinfo, encode_int(offset), 1048576,