diff --git a/.gitattributes b/.gitattributes index e50b5d8e2e..04899a7da8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ /VERSION ident +spec/fixtures/files/* filter=lfs diff=lfs merge=lfs -text diff --git a/Gemfile b/Gemfile index bac2be4390..0f803df1c6 100644 --- a/Gemfile +++ b/Gemfile @@ -141,4 +141,5 @@ group :test do gem 'database_cleaner', '~> 2.0' gem 'webmock', '~> 3.14.0' gem 'elif', '~> 0.1.0' + gem 'memory_profiler' end diff --git a/Gemfile.lock b/Gemfile.lock index b9c43c8c9e..8503e428f6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -299,6 +299,7 @@ GEM net-smtp marcel (1.0.4) matrix (0.4.2) + memory_profiler (1.1.0) mime-types (3.4.1) mime-types-data (~> 3.2015) mime-types-data (3.2022.0105) @@ -552,6 +553,7 @@ DEPENDENCIES kaminari (~> 1.2.0) listen (>= 3.8.0) lograge + memory_profiler minitar msgpack (~> 1.7) nokogiri (~> 1.16.5) diff --git a/app/workers/process_docker_image_worker.rb b/app/workers/process_docker_image_worker.rb index 61d856ab57..62ea19bccd 100644 --- a/app/workers/process_docker_image_worker.rb +++ b/app/workers/process_docker_image_worker.rb @@ -26,10 +26,10 @@ def perform(artifact_id) .body # unpack the package tarball - tar = gunzip(tgz) + io = gunzip(tgz) - unpack tar do |archive| - archive.each do |entry| + unpack io do |tar| + tar.each do |entry| case entry.name in 'manifest.json' raise ImageNotAcceptableError, 'manifest must be a manifest.json file' unless @@ -66,6 +66,9 @@ def perform(artifact_id) end end + # not sure why GzipReader#open doesn't take an io? + io.close + artifact.update!(status: 'UPLOADED') BroadcastEventService.call( diff --git a/app/workers/process_npm_package_worker.rb b/app/workers/process_npm_package_worker.rb index d45a666768..ea6fc488cf 100644 --- a/app/workers/process_npm_package_worker.rb +++ b/app/workers/process_npm_package_worker.rb @@ -26,39 +26,35 @@ def perform(artifact_id) .body # unpack the package tarball - tar = gunzip(tgz) - - unpack tar do |archive| - archive.each do |entry| - # NOTE(ezekg) npm prefixes everything in the archive with package/ - case entry.name - in 'package/package.json' - raise PackageNotAcceptableError, 'manifest must be a package.json file' unless - entry.file? - - raise PackageNotAcceptableError, 'manifest is too big' if - entry.size > MAX_MANIFEST_SIZE - - # the manifest is already in json format - json = entry.read - - ReleaseManifest.create!( - account_id: artifact.account_id, - environment_id: artifact.environment_id, - release_id: artifact.release_id, - release_artifact_id: artifact.id, - content: json, - ) - - # all we need - break - else - end - end + io = gunzip(tgz) + + unpack io do |tar| + # NOTE(ezekg) npm prefixes everything in the archive with package/ + entry = tar.find { _1.name in 'package/package.json' } + + raise PackageNotAcceptableError, 'manifest at package/package.json must exist' if + entry.nil? + + raise PackageNotAcceptableError, 'manifest must be a package.json file' unless + entry.file? + + raise PackageNotAcceptableError, 'manifest is too big' if + entry.size > MAX_MANIFEST_SIZE + + # the manifest is already in json format + json = entry.read + + ReleaseManifest.create!( + account_id: artifact.account_id, + environment_id: artifact.environment_id, + release_id: artifact.release_id, + release_artifact_id: artifact.id, + content: json, + ) end # not sure why GzipReader#open doesn't take an io? - tar.close + io.close artifact.update!(status: 'UPLOADED') diff --git a/spec/fixtures/files/expired.lic b/spec/fixtures/files/expired.lic index 3e3c3ac6bb..369c59ce45 100644 --- a/spec/fixtures/files/expired.lic +++ b/spec/fixtures/files/expired.lic @@ -1,70 +1,3 @@ ------BEGIN LICENSE FILE----- -eyJlbmMiOiJMbU01YWNYUWNHY2tZYnB1WUJmMDVTMHJFd1B3bklhdGt2N1Fy -MGxDWnovcEFwbGh1OHpJOGxrZlpNY3hRZWFydWtOUXdLOFpCYXJzVDUxbkh0 -Z0VGTVN6TGxUc2hCRWZURDRKd01XNUlubUE3MHdNbWR3UkpVQU9TT2xZTE1v -Z2NpaTl0Q2VPczQrY2Nha0RsU2hzMitmQzJBSFAwRUVCYjQvRjQ5ZUh0Qk5C -VXJ5cHJUQXNOb2RqNG1ic1ZTQXowVUZiZXk5c2Q3OTFGdnlyaVF0MU8rYmVo -cjl4WGp0RmV3bThYcUFtR0tqcnU4RXVEQzdRWHduK1Fzb0ljRmI2OThkNnh2 -aE9SL3ErbE1velV5b09CSktPM0NiRG40QjdwVFc2YlRHeFpCdUxna1V3QW5w -ZnBJem9sbDR5RmNQK0hHWVo0T05VdG52TnZ1eVlFUHp6VTRuOXpJQmMyckk1 -Ym5mSkZSMFhBQ2ttTjNwczJzQVZGZ3E1UzNXQis3c0g3aHNyQ2ExNUNQYzcz -eXVWVVljUG9GV3R2UUczR3p0aDhLT1JIdHdqNWlKSlF6dFdBR3JYTjhvVU1Q -OWlPMkdRNGlEU1J0MGdlUFZhOVk4RUNOaWF2V1Vkbjd4dUNJTklRcUw5NUQv -QkEraGh0RkplSEhjYmV3V3lYNHNsSGZldlVjSVdmak0vWXkvRk1BWWM1TDIx -YjBmRnlxaHRTdVFXZG5HbmZ3cUlqSmI4bzRDaVdOd2ZIajJQc1FKTjR2Mm1Y -RGRCb0NSOWVCSG42MnAxUStoY2laUEZ6STlxOGoyd3huYkRGQjVDR1VBQUJC -b2c5SHJtaUxCUHBHNG1WY2FaQlNhWTdsNmlpanNGY3lxdVEwVnpLd2NoM1Nu -TUF5dE9jbTBmcmozZzd3bml4dWRIaVFhMCtxSDBHbzlFbHRHaE9FbEZjUlkw -b0xyUmZTUzZPM05jc2NBT3A0RFdFdGdnZlJFWkxaVmtxN0w5dW1qNThuLzJU -RFZaMllYNDAwbUZFNmxSNUJ0S0ZyMjd0Mmx6QXB1UFNWRGc1SFhRSzdjY3hO -TlhQSDdhbUptdzdmWWV4NnZYM0ZmWTZBNktwMXFYTk9keGVyWTduMmNUT1hK -Y3JxZXp1b1A2ck9WbUI4aTFuTVRrUzYvRFJSaGRJQy9SWWZHRWdONVlTdjNX -UkNsVDBLbjNrM1BOdzhvc2c0Yy96RnQwMHRmcFNNSTlodm1HUjhmTHdReVJ4 -QUZrNDhaRE9TeGVMOVMwT0N0MHZxUTg3TUxoUGUxV1NneFI1VkthWjlTWE55 -REMzeGo1eXlGM0lCOXgxRHBSWFRBaytETkQ3KzBjOUJKd0RBeFJjK3E3czVv -VGJnVGdUdTJyM24vUmpIaXZBcHJERlpPOVRSdmZOTTl3ZlpvM3VIZlM3MWo0 -b3Y2ZkRvbkJybzdRZEdmd1FaTTUydWRja0hnZTlVTU5jNFVYbXZhcVkzUlVZ -Yzk5NnpnMWNFQ09DMVBleUZVRVA4RFFRdDRMaThlb1FUTkNFUEhIZitya3Bh -T0l5QlRyblBmdnRSMFFJai8wZzd5Sy9PME9abWNJZTlTQ3c1c0ttUitNckhp -RjY3VDQ4b29TNldybHhlc3E2ejFnRTlwME0rZXRnYnU1UnJtKzAramdmV2Ir -ZE4wNVdmUCtxQ3BZdGRwL0o4YmJSWWxWUlExWHFKWG1RRzJ0MW84eFk0YU9m -TG9JTG4yMTQ3TGZSY3oxRUhoSzBOazdrSXcvZVFsL0pwMDhIYWZMekhvSzVl -NmxYUGNTWnhjM05IbnZxZG1haVVXRVgzRGNNejl6UGtXRmFpSjlkZDA1cG80 -aVBGemJQd2RQYXpSYWJjcy8zT1lUT3RhcGVTTTJyOXlLeU00SGZyS2NxcTEv -aW9WMlVGNEYrTTloenNBRVRvcEp4ZjI1N2dLSmRJUGUrYlZWNTM4RUVReS9M -SXVxTlhnUW9NRjVBVTU5eFdyRnliMkRUN3BrSkxlUDJudVA1T0FJM3BCRURs -WkNUM0xiUTg5WVZBOXk1WTBTK1ZKNVpvbUVZdThzYXAvMXJqWXZERCsxMTZ4 -eUhCS1RiT0dUeWI2RmdxQkR1elhXZ3Blblo5VWRtSzk4OWlwT2prLzFsaWpF -WjNHSmFFd051U0FMeE5zMzZoaDl0bGxwVkM2Ny84RjI4RGhpZFFjOUJKUDJn -NFpYd25jcTRhL3BySWxRN3hVbjhSLzNydDlqSXhHSE1qWE8ra3Z3NFBidDA4 -ZW1sZXNEcklMbjBrVDRreVJKSEMwazMvY1FES253bXhDdldVQld2cUtEa0pq -UXRHK1YzK1pvVm5IK2lQRGZSM0d4YnJSRENxNnM4UVRKQm5tbElnVHNobUZN -S0FiQWoyUHRpNWVjNHQ0azZ0Z2FMeDZaTExpRUd6MnVoWFpDUzJ4RVFGbHhU -ckVEbURqQkkrSmVoVUJXV2N4bUJNc2FsdWxLTCtvdWJyQWxNOVkrNThNM3lR -SmhEZWNvL0pyZU1RVEpEYmNqS0Y1L3ZQSFpDanlSc1dhdURacE1pcVlCNzVG -UTlRdkxHNVo4MWpLVVZJZlk0NTRGL1FCRW9ESDBqOXREV1FSQWJRZCtaTWQy -K3VyTnhMVnY1eHQyZ3BNeExBOWZuOUU3aHpXOHhuZEExdmszZHE3MkROeXhy -aGtMU2xlSFRiYmNBb0p1b1FDRFdoVWFmQ0pvdE5COHQwQ3c2ZEpGdTBKajdV -Si9kWCtPN1g5WDROWm1DUzM4K3hXZmpEWk01OWcvcG05VXF6YnpSc2x2WHRV -Z3VKNXlQRTVsMG92cDlPbTQ1OWcxZlpiV0xhNjlpUVRaQm5nNmVnOS9nVHY4 -MjczK1RlTklFUlJZVmx5NERUWmwvOVQ5bkNUQ3JSUmUyaW50L2NRVDRIeUcx -ZnQ2dGZkcHV2d0VSQTI3SXNxOXhUdTd4UFFhNWdRR0NlbjdJSG5WZlVmbnhv -R2RsNnBpWUhGRVNITk5lV2RrY2hqQkR2MkxyMEovUU50WENLRGxpdHF2L1BL -UUVkelBKZnliLzlTRHI0RnJadGQ4QXkzSS9RcFJ4Mmc5VDR5R0pSUTFCV1Rj -RDIyaXpQckx1aFJXdjQ4TVk2c2lNaVVnbCtNWmlCZ2QzbUtia2VUdC9rNlBC -UndSYWd2YjIrbGRjdXZuT1Q4bjVmUUV1MXptYUcvZHovV3hhcVJrdFNxVFJl -VG04Nk5SbHBwVHd1S1Z5RlZtbFhCdEZXSEwrZ01jQ0ZqSytvNVM5YTFaN3N5 -Q21Nei9ZQ1RBOW5NSlN2MlFKSVdBMWIzUzludTRyb3pWNjZjTnJzSnZ3ZWRa -bXhDMnk5aUhFWGY1SUhaNmFIWXVDWWZBWTFObE8zWDlKN2REU0UrNGFuQU12 -ZFowRXVBV2tOaXFqYnhPbTA3T1VWWXRMYnd2WXBubjNIRHA0YllPZmtwb0U5 -UW1FQm5KZjd4V0M0Sk00ZmhhREtCNDVERzJacHFqOE82NXQyTkk2NVBlRS9l -Ukd1Zkh3a1AvNitDNzFHWHY1czhZdUFJZUs3SHNHblZzSU53VFpRRmRCVE1C -a1hPZUozV3Q1Q1FyWGtQdTNrRU5ZQnQzRFNwM0FoT0UyQWdJd0U3S29sOC9H -U1JpVit3UEhqak5oU0svNFZtcHhIOTUwSlB1ZmZxcXIvTFhOSXAvWWtsaWZT -WVVMSkU2QThqVytrWXdjNUdtZXVsdTFpOXptYWxmQnVRTHp4d1kvekJkcVdv -YnhiNlFUcGhFeGlTZ2dBPT0uTExhTTVxQkVpSTYwaHRIMy5NY2Iybklxczd0 -UnA4SDRKNkM0TDF3PT0iLCJzaWciOiJ5V0gycWRkWW9haFArcjVQN01ELzJP -REpxTWYvNy9udlE4U1pkaTkzbnUyWFBPaGU0K2ZucXdyVzJYbWg2Z0FRT1Ir -OXp6QjRKdnpXdEtxMG5TV21Ddz09IiwiYWxnIjoiYWVzLTI1Ni1nY20rZWQy -NTUxOSJ9 ------END LICENSE FILE----- +version https://git-lfs.github.com/spec/v1 +oid sha256:2084119fe3a1137a01ff2f93fe0a94264dbc2bb7f4627e8676ff77f1354ed664 +size 4152 diff --git a/spec/fixtures/files/hello-2.0.0.tgz b/spec/fixtures/files/hello-2.0.0.tgz index 4fd0360acb..61f7c40402 100644 Binary files a/spec/fixtures/files/hello-2.0.0.tgz and b/spec/fixtures/files/hello-2.0.0.tgz differ diff --git a/spec/fixtures/files/invalid-1.0.0.gem b/spec/fixtures/files/invalid-1.0.0.gem index 29b46386dd..c9de4b0304 100644 Binary files a/spec/fixtures/files/invalid-1.0.0.gem and b/spec/fixtures/files/invalid-1.0.0.gem differ diff --git a/spec/fixtures/files/invalid-2.0.0.tgz b/spec/fixtures/files/invalid-2.0.0.tgz index c5b7e849cc..6a7daf3907 100644 Binary files a/spec/fixtures/files/invalid-2.0.0.tgz and b/spec/fixtures/files/invalid-2.0.0.tgz differ diff --git a/spec/fixtures/files/large.tar.gz b/spec/fixtures/files/large.tar.gz new file mode 100644 index 0000000000..45b4fbd566 --- /dev/null +++ b/spec/fixtures/files/large.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:caa91b706594ed750488a2921bb0e442c6e641c8d0b4bbc8289bcc1d048454df +size 116271177 diff --git a/spec/fixtures/files/ping-1.0.0-java.gem b/spec/fixtures/files/ping-1.0.0-java.gem index 78253bb36e..7421d9b4e6 100644 Binary files a/spec/fixtures/files/ping-1.0.0-java.gem and b/spec/fixtures/files/ping-1.0.0-java.gem differ diff --git a/spec/fixtures/files/ping-1.0.0.gem b/spec/fixtures/files/ping-1.0.0.gem index 4f9766f168..f2338ce100 100644 Binary files a/spec/fixtures/files/ping-1.0.0.gem and b/spec/fixtures/files/ping-1.0.0.gem differ diff --git a/spec/fixtures/files/tampered.lic b/spec/fixtures/files/tampered.lic index 6b49e06745..6113b0046d 100644 --- a/spec/fixtures/files/tampered.lic +++ b/spec/fixtures/files/tampered.lic @@ -1,123 +1,3 @@ ------BEGIN LICENSE FILE----- -eyJlbmMiOiJJd0RxQmc3N2xvUWtHQ0lrSTAvYlZNMFFMNm0yYmUwdCszMSs3 -bEhkQjhxcFB4L0RldW9HZm1qcndpc0hCeUNnejBHTGhLMTBYRlQwTTIvdktG -TjdHNFV2UXpiMEZ5S3A4eGpBWWpuVkQzbGlxTmdFUVlHMTROZUpqc1BJczlu -V0xMSkVQSFcrL1R6Z0ZEblFKSmxycUlRbmlIaGpzWmVRQmIzeVJiREZzTTBh -VDFQYWRKVVVmOE51aTcvUnlBMHR2Z1U4QVFLMUJVdlFBM2tlbmNoempkRDJG -a2tIZjVMckNVTFMyQlFhWExsUTJJWnZVdktZM0liM3Jmb29RdHdLYmIzRmlC -UW5DaUh1ZEJjU0ljT1BkRGdRcmZCYkhsYlpPcTJXazlSNklRQ2VCeDB3M25F -MHFnaVRjZ056dHIvaDl6OUNZTXY3SEJCMXVPSFRYQmdXQmVMV3c3SDRSd3JJ -a1pIUnMycGNsRDBGS215UTlyamR1VHJETjV5ZzJydm1KRGpSSm9nSkxaQ1Vr -YzJHU3BzMGtHdDRuVEhjUDJsV3NhYXJnRDZhRU1sdm1qMGwrSUpHejF1bFNn -VUxyelFTU0tyM2dGZ3JPbVdRNk9QZDlXNXdPbndFdDZwdkc2SFpKM042akQ5 -MVBJTUJ3emE4OHJwOG43aU0vWG9aeFVxOXpFQzdXd2dyUXFiZUJ0NUhidTVD -eHRHZ1g3VjUxRHVuQ21EYVpzek5LNXJ0K094ZzUrcWczTXNiSmdaeWk3dzY4 -aFB6SHdadzhhTHVOYzFpVUE1L3ptVHhwelpJaHdkZWZJeUVWc3RYSEIvWWZL -a2s0Y3NDWWpUOUZGYURpMHdqdFJCZUdQYzRGTGFsZjNXSTMzRjRYNlErRi85 -SFNLa2xLZTBacC8rZXpzR25tTlpNajN2TDVqT2t5MU41MllDZDdaZXZHLzRJ -Q3VQU0YrRy9naHp6VEdSRVRybGw0eU5WQ0FwWlh4VUFXcTZ4emFQa21ENERJ -L2YwVXRRL0MyN2RjSUlERkhoeExxUWYvdy9jSjRFQmpvajhGcWZUcVZxeG5j -K0NCNTBWRy80ZHNzUmNWUk9FZ1ZWbERPalI0czJuN1B1cmRWdlRLMHl0SG5q -WFc0ZkgvMkN3elBWSVY0Q2RyNFZiNHR6ZzA0Y2NlT2o2L1pxdXBEQWhLaksx -Y0UwZTZ0ZnF4VVNQTitDOHl4bjg1V1JKamFUUVFGTXJsOU43dmlJZFNxNWx6 -aER5d1MwclN1L3dGUndKd3pwTFdpelJ0dkpPbW9BSk9TdHAzemdkdVNoK0pl -eDZBamFHN2s1eFdieEo2UDZtVWM5bWVpSU1kUmdxOUlYUXFtNUtrT0tDdUF0 -b2IzTFlhYkljSFpaR0VRTFlvTFFaU1dKQUZndWd5TVk5a3F3c0c3aHJaTTRq -VjB4OUM2TFZHMEtQU1FzaGFka25Ec1l2SDZ1UGVTbHpONGdGUkZHSFVmWjNO -c1RQTWwzUXFNb2hrdUlyT05TcmY4NGl5UEdVRFhtUXhCMDJmTnhiQmxBOUov -Q0RwbkRnWG1BU2xwNloxam9qRUcxQTNUaUM4c2xENTdON0ppV3ZleWZQaWdV -YWdYd0M0eEVIRGg4TkRMcWpzYWVxanVWNVNkSXQ4ZU13RGdCbDNINjJvWW1i -bStLR25vZXhweDRCaWl0MGtlbHpJT0t6ZFVtS0lBR1BQZDJrdmVaOGJiQVRE -M3FJUXVocmd2eGszajVaRER0MGhQaGFsaytUZjFQN0g2TUx4M2h3WFNJdlBG -NFVIazFBK1hJdU5BZHdnWHZvVkxEYXNwZnBjZ3JCeXVBWDVRS0NTb1NiMG9G -Y2NDUUpNdGFNclFKeHRGeDNDc21EdE9aU2ZyQ3lzMFg3S2dYVGZ3UmZoRmVR -eHB4VlcvTm9Hc2FBOGdsbURyR0JrVm85eFFJdDNNOXNqbkRKQlN3S2xoVDNh -K1BFSU1ZeWRUSFUwaVlhVW5kN1U3VFBoV1JVK1pFM1REL25CdENFVjczbU1M -cUFqdTQrY2plOHFkSHRwcUozdVdKS0VjeXhvdk9RZnpnRHQvU2F5aDdaN1Jq -OEM1RGN4cGZnS1FPM05CaEYwbytNR29ld3RxNjlkblE2bmZBY2pxcDRvZ0Zr -WWltVm1DSVUyN2ZKV3IwWEZTbFZYdmpGM0dFN05ZV1I5ZkJUNWt0clIvekJY -RHdUSXcrcjRKUURkVGdXOXVTQVNhSHhCQzB3cG82engxd2JtWUVvSDRHeGt4 -VTNDWTlMaXNTV2t3VXc2L0s0Vk1seGJ6Tm4wc08yU200OXdOeU5KL1IvcGlT -UFVIZjUvWnIvL2hWNzY4Q083Nk1maEZCNnloVFY5eWNtK2Q4ZkhwaitQV2dG -UnpGYk4yRkI4VEs5ZXRCeTVlNE11eHZldnR5N0JQY2xJVE1FZXZsNEYzRWZx -S1BDa0dNNnZiUktvNkMxUjBSMkN5S1prZ1ZkWmh2TkJhUDhwZTRHbnVxclBk -RGY2dFNyZFkzd0N2azg4aTRKV2Y0V2tic2Y5WUcwMEp6TGtTUy83UlZ6UG9Q -cFV3U1A3UDFYVjlvdkJCUENZVHpkVkZvTFY5V1dSa1lHMUFvQ2I1U1JaQy91 -WEs0eHNOM1V6NlF6M0VSbzZ0MzMya2w4ak9HSU1jTkViSVN0aGc4UXg2UHdS -bXllNTBkVmJVM0o3Mmd4UEdCMWQ4aU94Y016Q3RVWGhuMklvYnZDSVN3cGlL -QmlSTU5ZNnlBWHhzZFBDRmhiVU1nMVlBOUp4Z043YW1LMy9XRFMrYzIycHgy -LzVYb292RHVoZFVuRThMYWlGQ01HZGgyWlo1MXpFNnkrYkpsZ05XV04zWXJ3 -Zmg5VFZ6eUJKS2c1TVVEeHVtSmJ2SkJ4aXhWcExTa0NnTm1sSzJldUZnU1J2 -dFpkcksyTjVLNXJMdk5oaHNiYTdpNUJQN0ZWNmtydEcrL21uZDhsd2ZEelI0 -ZlJaalM3blhENmRTNWUxVVZ5eW0xcGZmUTlSZFFTeDNaSm5yQ0FGdHloUHIx -Q3pxRUY5citKb0lWdk94NU04dVZIcmdkM3RqVTZJSy92em9uNFRRSmY3T016 -K1ZNYkNZcDV1ZTdVdkhsbFFWQ1NKL1g2RHJpcWp6Ty81bFllTzhTUStJdU9y -eXo1MXFMRFFPZk5vd1pWdVlESU1jQmlBNGxVakJJbUc5N2x0a1lPNFVjU2N4 -VFdTandoUTVqNU1pWE9ZTkRGSE4yZlJvS2FtRDNVMExFcnRkVzdlMjVlREhB -M3VTSGM2U0Y1NTB0azhyOXZVQTRDODg5dlJwQ3RqTzk5RlFkVnBRRlR6Nmla -c1FTejRSbFA4WXVJelVmTHQ2R3R0dGJJamVlWnBLU285M1I5YkExQTZ5RFdw -ZThwcDN1Y2hxYVFHeU9iV1E3V2tib0lxU0NnVXVjRUdkbXhXY0pXYnZ3OGk4 -eENRaklvYXFNZStQNDNiNkVmUDNxYlhZZFFDV0JzdzJTTmV0bU02c1UrZnNX -VnAvbVYzd2hkSzM2Y0Q1VjVmeFVjSmtqQ3RpbllEbjBDdzdJTVVNQUhleDlZ -YjJUZzVLOHV3V3k1dWhIaTRYMFNFYnphOS8wV0ZONnJFd1NoeDJzQjdqK0V3 -QWZIZkxNb0ovc2FwZmhhT2dRemlPTkNoWTY0ZnFaa1Q1UWpSNCtyZlk4VjY1 -RE1VZVZJMEc2Rm1kVXFRUEk1bVQyaDBlaklaYU9GMS9Yb3lEUHpBdW5XRk83 -bTZ2TUQzKzdtTGNXbGoyVXBYRzNlMFJXTEN1UU9oMmEwVTVxbjlvdytFS3J6 -YTdLYWFnSlA1Z0h5NDNPelU2c3RpdWhWVjUwQ3dwdVZpczVrSmFHcWQzbk1q -V2tVUFVmeW9YT2FOL3dXbkFaRDhVb0VQV2xKUlZyUmNZMVZlYTRubHJiSWNx -Snd1WWJoQWprU3UrdjJCOFJOek83TjhvNzNWeFMwb0JPMzlmUTZMUVgvQzd5 -c0JvNzNPRjh4SklidDlQclJHeENFMWRLNG12UDlpbFFDNmVHQmI2aFA5S3Ja -Wk8rSmZTeXA1OTNsdlhjOHZGUmx6TUFCWE9KRzdkdzB3LzNsL3lVVnZ0b01C -Q3kwVnllTnY4VVBWU2lHbnpja3Y5c0U2U2p0VVhOLzBWdG1Ccy9GK3g2MC9y -ZStVYlNqMUdLaEZRRzA5U2FJQmZGbDNMRXZnczM1ZHBuV1dnWlE5TkFSN2hu -anEybTczVGhkMVk4L3ZVeGxQTFc4ZUpnYnBPeDFRSjNmTUJzbEFNVEFXdGcw -MHhmWHRKbWwvMGZ0dUI5ejFzaXVSaHplZURkc0FHRE5WZHR0RGcvU3VEc0pr -S1FsUnFWN1ZnSXRPdzdwMzY4WUdMSnJFRWQyc3N4WE96dXF3NmUxc1dtVC9q -YVgzSzBjZEgrWGxiRTVuemRUYjdvTWxVOEk0RHp1SlYxM2E2YVlRWmhUSFNU -a0NIY0Z6YzVVT1h1YkpldWI0TUNkdVhhRDRNVFMxMXhVM3NRTGNzTWtLdjJM -L29meUN1Y3BnRnNFWmQ3OFU2a0Y2WUhvRTlyTWg1MXJiaE1SdjJ2bFcvZ1Nr -d241Z0NkU2NMUEVEL1JmalFBb1VZRlY5V252RTBKQmw1N3lCWUhHaHIwUXlI -M0p1VWtaSFhqR0RVWlRYOEltOHd6eUNzUmFFTzA4M1JrMitYNU5TbEhQUmt1 -ZDBETC9hSVFBS2NjcWRNUml0R3hSRFNwZ3B5RWI4d0tMZmFnZk11NGpaWUtG -OGJlV3loM0xkVnNWTEFRdjd6SFl4Q09VdmZUZ1BCQVdZUjY1eTZmaUErMFlS -SnZlTUZHNDdtbkRJVFNwdE9MN3o3WG1mTFVGdXU1ZVk2VFpnMzhkdkpSSkFy -RzlFTVdWSE9wTXRlZk1uL3JpY25SK1hUODh4akNmZG5UTU5abnRrTXkyejhO -SzRkemVaWEhSdzM3TVhxWEM3eTIrOU1hSkxod3VVNGt1dkRiNWVkZUpwdkhm -bUlwaXNRNWd3NkQzcGdCSG9kL2Q2cEt5THJyWnZCSFMvMzJZODNnSDgzR2Qx -NDhqRE9tdTNCd0pMeFdpQ2g5T3MveHd3aVYybDRVSG9hdFpITDZvaUJOUE1R -RjJGbFVLNXpOOXJ0WkwwaTRGOXMzckN3aUd4TExZL3VObmRkTm5DaHVFcVo3 -YmRWZjFkNTdNa2pHZ2NnNWErOTB5WXBta2R3NW5vRkRjeGZUSU5iK2tMQnc4 -ZWxoVFE5K1ZsWVJOUGVSbHZrNHYzbHp1aHV0Q0p6TVd2QnhieTdVQzRKOTUv -cm9JNlEzNnBLTzBaNVdWbDNXaTBjRnM2Y2ZBbFA5c0hYWkdSWG9URzVQSU0w -Y1BjNXBqRmIwUkVic0w4WUpGaVBqZk83d2t2VlJBYXVvK1dDb2piR2xlTUhI -QjBKWFV6WS9xZis0bEZUVjJjeHJaZjFadGp4MElleFR3ekVRUkltV2hidVhm -RnNXNE0zZTdSREFNUmNuR1hzZUtiMHRqT2cyVDI5R21oaUJYUTQzcGlob2Iz -V1VyM0dZZ2JmS1I3bnlDYVJMSktQZkpIdWhoN3ZmWE5RV1pGZGVZbURoYWwy -MUIxVkQ4azhub3JaN1Qwd21zeFJ0d3I4VW9LT1Qya3NzUU4rdkpxUis1NmtH -QlVIZkNjeGpvaVB6SXoyd0J4YytEcXFZSFhQUGxLVkoxeFhYUjBNN3ZTNllr -V2VwNGhCRG1rN3M3MURxQW1Rb2FaN0NjNVQzMGZlWW5UZ3VSMlFTSmR0MUh2 -VVhPT0ZpVE5PTE5ZK3Y1OEJyemdOWmFZSU40OTRPeUs4ckViNWN5VWVkQkw5 -SDM0VTJQcEpiOFhzaTZ1SmdPcCtkZEJNaEREWGg3QjkwSVRyOXoraE5YQ2hZ -OE4xZHBxakhhRVV0cmVHQmF6R2VTSG5FTGdSL2xNQnV2eWNkOGUyR1pNWCs2 -ZjJ3MXl2R21iWElvNFdCMzdLSEU4Vjd1ZVF2d0Qvcm9tTDZzMXR1Mk1PcUFV -NTh5cllSQUFjUENvUzM3elNBcFhFTU5KcThIMldjb0JMcXE2US9Rclhzdk5t -aXNFeDdGZW1JbW8yZmFlT3cwZG5uSlEzUjRUZXY4d01Td24veWVWdytONzRJ -aTE0WU9rZG4xanBXVmorVkNVaC9ObW1sVGVOakRyaERVbVQvOGE5QTFNTGhn -Z3FxbVFVVHovdmpHb3lvdHYrdXlPVWJPZ0t2M0NLSDZ2aVVQajgyRlpJZWpo -cXZ6YTVxMFJEam1HdUw4TXQ4TW5sOW5mM2g0Q1pkV25ZdzUzY3dqR3MrQUEx -TmJLZFR0UUVaYmNraDJWb2hjeVRwZG1BbXlST3Z3TjlEdzYzRWtnVlM0N3Fs -ZVJocGVKMTRJSVcvYjlsYWNEa050Q2pPYk42cUhZZXpUVGJvb2pmeEdBTk1R -Sk9WTnVqcitTSHZuNEFUViswRjc3OFRZR0laczlISjJqYjA5dXlFTW9nYmN4 -QjVnODdFZFJSQUs2cjE5YWhGeHptRHZZNTcyYlBmWDRWR21hSzgwOXNGZkRp -cFpWZmtQV2xrREtKYm1GeDlUZlNROEMrT3kwQjVEQXJvUFhRd3E1NG0wbllE -ZHA2Vm5mcC9qZzgzV293eFgzRkxyU2pleFFNMFJTQkl3WDdMbUJvNXlzU0Ri -Tnh2bzdTL3pyQVg2aGltbExPVDRDQU5NYnhqdVEwOTh6UUl3UGUvckdsaUVD -bFRoczJjSlFLQXUwWVlNa3o0NHRBcENJdUNsTnlGWlVkY08xNUhPbGMyNEhl -OWQrSTEzOE1OcGtRYXhjM0Q4RFJBdjZpMnlZdFl0eVIzNEJjT1BSa2NNY3I1 -ejlMd0phQUpVdmZuZkgvek9EQ2dJWGkvZ1RXL09hOW4rZGFVTTJjZm0xdERw -L2pnWW5zRytKdUU9LlhmamFwVnFuQkNCZ2l1d2QuUmhCK1pWYTFMRzZtRnkz -d3Z5UFVjdz09Iiwic2lnIjoiblViRDFVU095bDNvQllJNnFqMElIeGN1YWlw -cEI3ZjlaQW1PT0VEMHMvMytzV3Bxa1hhUlA3YU1kNWtEbVRoQkdRTFVETzNl -ZS9KWUQvdGF3YUE4Q1E9PSIsImFsZyI6ImFlcy0yNTYtZ2NtK2VkMjU1MTki -fQ== ------END LICENSE FILE----- +version https://git-lfs.github.com/spec/v1 +oid sha256:bdf591aae6bbf27f34dfe25da87325d93abe61429f5c96ab598bf2f7ba912940 +size 7381 diff --git a/spec/fixtures/files/valid.lic b/spec/fixtures/files/valid.lic index 1e3d753b99..cc430b7153 100644 --- a/spec/fixtures/files/valid.lic +++ b/spec/fixtures/files/valid.lic @@ -1,230 +1,3 @@ ------BEGIN LICENSE FILE----- -eyJlbmMiOiJEVjNjNGhpUklCdW0vNEp1UjhyU1hEYWJ2QktSM0tpcWNGUkZD -enV6VksydDVnaytpdnpJY3crVjBNM2k4aDJzaTU3V2VRWUNHMlpFVEd5aEZx -R2QxQkt6bWJzdnF1Z0VJT2dhaXVLQy9sNjVmZTNabS9kU25abFp5NGlOVFZJ -b0tPMmE4NHhTOU8wYjAxZGN2bWV6SGpNTlNLa2xXNk9ISzdsRk5TQ3RqbWpo -MEg0eWNHUGpybDNvNGJFZE8reDdxY0hNWWlOVHRBRDNoWGlRNzMvcko1Y2xS -V3kvY0hUM1RJc0p1ZUZoNlRoWHFVS3ZEK1BwaGZJNExIbHJBaGxJampZZm9k -ZWhvNVhXa2FzUldod1pjR1RFRG4wOGk0TlVBUVRuc3pyM1J3YW9FTS9kc0JH -QUk5M1hZbG5UR2NQVTIxNElDZndzak5xbXpFekJ2bXJxdnBaVDlReFRUeUdG -alhWMlRTMDh2UlRybVMxbTFUcDhoZjFxUTNyTHFVb1BKMlNpMHZWNTh4U0tE -Szh5M05vZVVpVU9FUW5aWXRPakJyVUlVNWs1WlNmOGcvQitNOGpxUnRTQWk0 -aDZWN2c3VHRlV2RWdHVnVUthbmFnWWV1OXBxS0xjUCtFUlFub3d2RTVlcFZp -bzRweVlCWUVCTzEveDVrZFhSSFBtU1dJdU5iZW1vY2IxVk5vSXNRSm15OE5l -ZGNybUJJNUZrdkNNZTV1VXVOMUNMRlpxbFZhbDhZZmZ1Y3FXQUFXU3NMMlFp -RlNHUU9iQTVad2s2VXJ5MmVjaVQ5SGJJb2VpTjg3S0hXZmlScXVtc3BibFI0 -M2IxMjh3ZUxKWnVacG15dGpXb3hSOUUwV2lKdHhxWk1PR1J5S1lsdzMyNWJm -cTdQQzFQR2oxcUZBbWZHWlB2VlRMTys3T3VUUWR2WFVGN2VDNnFXYWQ3M0hq -VTluN1l5dzRabDM3N056dENiT2s2Z3BZUjhIMXdpZnhIdElQaXVlVHR5Q1lv -bFRERm1yV1pUQ0FWaldacnlSUDdRM0FxUWRGZElUZUFjcjZVQ0RQWEVpN0VJ -ZEd3V1B2UFZCUVZMNWF2bUVaLzJQcWgwTzd3YmdkRktEbk1rWDhwQjRNRHFQ -MkVSTUVoL3hyMVlCWVdkWVRERFZNOEgwMjBMVzE0NlB2YjBCby9tVWEybC9I -UWtHQ3crNEVZcGdCVG9QdDVjUlFybmxxVXovTVNWUkFMVW1jSDBOTUkxRUJ4 -K0VaVEQxMXlXZXJBSEFXRWRyL08vSVZ0UlZFZS9HbmorRDc5azlDbC8yYWtG -V3FXMi9oQm5DWlNlWGFUOW1XS3FmLzM1OGF4eE1VUW1xT3dJVHBnMVppZ3VC -NlhvcDA5N3N2d2wwb2M2bm00cVNvM2NkcnpPZHU0WlZ5WG96cWl2R0d5Z1Rp -OGljVU5DYjlxbEtERFBKM1Z3TnBXQlcxemZ0TEZnQVRoMVRGaDF0b05DaFUz -U01ZN2VKc2EreWw3bzM2VVNVMlBPR0JRcEN5V0pockRGNDMvQ3YvY3kyaHJj -SDA2UktWWCtvT3ptN2VMZjl4LzE5dU54NGhKc2NIZFZ6Snc4YTV5dytvZzBH -cmw0dVdobTdWanJDRk4vTy9pS0h3ZFlETEFmSGl6cFhQMkplZE1KeFNwSDVG -REgzWmRwQi9ESUUzUUVaYzFleHo4Zkd4WGNJVDN6TjRJNG9ycm43RU40by80 -c3E4Wm5qcCs4TUJ3MXoydUN3UFh3RU5aRWxwQzVIZVVwcWZEc3grODBoaW1N -YmY4TWRPcjBEYS9wRzVKZ1orclByU0FnZDJIcjRUamFKc24vMHdCc1FLQmZM -OTduc21ESXlyN25GWUhKSEU4ekI5aTQvUHlHZUJkZGJwTWdHN3Y4RDFNMlNt -RW8xY092d2dKWm81SGdNQkFhV0h1L2d2RjZKL0QwL3piNi9YVjdvOEhiMkhZ -eEwyeE5rTXE0ZU1mU25CSlZ3Sk9tY3RrYXp4RVNXMWczdm4zamNlREtQRXNw -dW9kVGxZZmg2NDdydGtXVVJhR2d2S2tVR2xxTDROVS9KNDR2Szg3QURULzBJ -MGNXbXF4azA2TVhDbWY5VUFJZXhuU3o0TUtWSkhIOFVGY2h4REE4NGJlR1Rs -elpLVE1wdnp1OVd1K1V3ZzBvNm5md3hhMHNOUE5GNWFsdzkwYmxnUi90VE1T -aGlvb204SGIvUC83eDRxN3VMT2RDZHJwamtZTE1HRnZXRmJrbWtabWJMYTBp -cGdvM1JZUWY4bzhXRkRZSlFUWUV5RWxRMnYzenpqSHptUjZ0UGR2UHlmUXMv -WGtpU1MxdXlwZzRVRklIYlVwMDhYRjdMdE5rZDdJVlN6N0p3WHBWcnJDV29B -S05XUlU2ZUtybllxSHJsMG5hbzZ1SVlOSW0zdWRHa0x5RU4rNUhPcHVZV3cv -NEFmcENKTHJEYjNFclBWd2RqVTk1NVV4OFBoUnE5R1RNOE5FSHRZRmpxU0R5 -VWt0b1RGU2hYb08zQTVnWHBZbW5tRnRyMFpoSkRFTUVGN1VjUFZvV2VGbXFQ -UTNYSzB0QXBRSVdXNkN1UXJJSVIxanNvN2JqSzFZN01zbU1FU2JWUFZ5SEQ5 -NS9xYTNlWGlXeVFMOXBGQ0tDRWR4Ly9rRW1HV1B6WXNVYy9aUzVnQkJ6N0VL -cjhGUnhnTEdFeHMxa0E5Um5tOHNzREVHUHd1UTgvZFo2dEhCNmRCdUNVZXJG -cmlpQ0FuQzM4RTd2MnFnV3NPWENqVHoxaFdDYjJucjB5Qis1T1Y1YmdxTjJQ -Rm9FaCtPRDZOdS9ZUk5GdU5pTjVFTE9GYmNydjN5dE1DbnJWQXFUcWtKQTVN -TmR5VnZLK0JKUGdwR0tPTHI3K0k1YXZ5SEhkQVFpa3BNVjBGMjhPSUFTa01j -R0ZKTWxsZlFYYkVvc3NXSmVpaEw0Sk15QjNQdmNGczVqTkNzNUpyVDJVcDJy -NWlPcDhiU2NCTDJ4ZWZ2elIrenNxVDdDdGNNMU9hMytLejZHbU9rV1lhRjRu -Tm94eWtEZ1NTMndKRkVZUFJ5aWw3U1pVdEVscFdnTW5JYitWaXJmV2x4NWNC -L1lBZ3ZsM0hoQ01SNHUza1RFK2g5RTI5R2lNb2hMVTcrZG9DYXNXNXlkMHA2 -b2kxM3piMHpkMzhwb05EZ2Rmbksvbk5idkxCQ1pKT1MzRlM2T3QwNGplb293 -aXRtMWVpZ0tTdFpaajhaRHdoN0Z5VnRRNUsvMFJFTDBZdnh4OE9yZ3d4NGNn -bGN4WjRSanQxNzJqS3NlOEpHbVY4THhrREdvNlpNeGJQbzVBVksraUM0ejBG -cG8vUjNWZHlGUzBwTFlGU25jZGJEdm1LcHJ0cUROYTkzQitYOUFpVEF4RE9I -VnlGTkMvdjczdkE5L2JqVS9BTEt2V3VDVVhnYlljTzdxbjh4WEM5YTIzV29w -TDFLWXdKSHFLNDFLU1A3UnYvT1hvbUFPMDZycnRWYzBOS2sxTHVETGxMNFJX -RnhkWklHaURHWFdvbjQyTEdkTjloTi9TYWdsTWZmOFVJQ3BYd1hlSUt4WjNO -SHJ0OVhCZWhaN0E2OUhmenJyMU9iMnROcFoveW91d3gzMkVqZGhURUpIY25D -QXBDMWk1aUtibWFMeXVCNWd6c2djeXhYMFpIbWN6bnBtaXJET1Q2MUxuN3FM -Mll5d1FSQmZjTTAwQmxFa0dOZC83MWRpK0hwOGhoMTZ6bk5JeGhuMGJyelUw -bjB1WHFVMWRFSjBNclVtNExGRXE3blNDVzArWTlKRXZic0R1dWxyNG9rZmkx -UXJUWmlNMkhJbWhsNTZXckVBdW9YN3Y0V1NMMjF1bk1iYWhqSXJMSnhuN3hK -bXhyOTJ2WmNvTHkxTlJwNFk5d0NLeDRpK2x5dkJCZmlBb3h3OHRtbUprL2g5 -SEp3K1F4R244TnFMcFc2bzdlOGVzZmIzMW5nbmx5aEZvd01MSWpiL3FNMWtF -bDVQeSthOXlnT1RIaDhEbEZTenRobGtaMjY1dnlRekRNYTNmMEpoZTc0a3dS -OUhZWU0xZHZQbDdHcnVzYWE5L0tQSXpQSmtUd2xyN1k5NWtkcWNnVTlYWkZ3 -bG5pMGdQcDE0MDhTRWkvbGhuNndUOWlEcW9lVHhUSS8zaXp0eWpic1pXMWtq -UTlNc0kyQTgwcnQ0VkYrTE5vZldiSTBmcGhoR01BNnRpb3BlRXo4a05EbmJa -SGN5NXdJYlJGRFNzTUdnc0ZMbC9aampHcW5mWWwyNU05V2NuZCtON2RSMDMw -RWw1U0RZeVpzblBZT21lWFc4WXVGV2h5Z3FBbjUzTXZvZGRiU0dYYlkrR0F6 -dEs1bmRyclBHT1Q3RERhamI0TjZiOVY4dzY5SHllY1UyeDA4Z0JUNGFqdzU1 -SDE5ZXhuZWNnUTcvVy9CUzd1RkJJN1NLYnRmQnZuc2FkdHlzUm05NDk3TUgv -UkNjS3VhbGEreW1lWVR0WEdTUTV2OHBBNWIwdDB2WUk2TWp0N0JrbktudnFt -dGF3SmFoeUlISlkrdTJaRlNGazYxVDRDNDlOVlEveEpiYXVCTnZTT2pkcUFJ -YXJBQVNNVzI2dmdIYmFKY1ZMQysvT1BPbUJnSllTM21tSFcycllUVFR3NTFx -bmFoZG05dElQSm5NQVNwZGdFV0tpRmRoTWtZUFhEeGdGbTFPYUYyZFcyQlBJ -MmtyMFY1L0pRRXpER1NMV0txUzhtaGE1OVZnVHNBY2NCa3FhK2kvUHkwRHh0 -aFRFOXA3SXlnOXAxRWdOYkgvdWdoNWVqM2kxMFVGazJoN2hOMm85VGF5ZWNp -eDZnYTlQbXR0akRrVHViWmtMRjBNOG5vVm03dDhXMHNIb2UyYjF3dWtrd1V2 -czVjbUJIVmhPVDdjYTVsUkI1dE1lQWt2NkpNclRrVWhoajNzWi9WQ05KTVBs -NG9GbEFwaWgwNGh5dUZnN3hTL3hhN282VkJiRW1PS01uMCtYZDhiekpPVGF3 -bzdoajVvT0I5N1lZM1E0SUdlY2h3M1ZWWENiK1RVNGt2cFNzQXJPeTMyS3Fp -U3JBdFBxbGlSeUdZVDNvaG1rZUlKRmx4YTRvcGFBV2JJYzBKSlB5dGNPQlc0 -TlozSnhjamltbndlL1o5aHV5OHVubE5FT2VEc0VOSG13aEwvdUxtM2o2T1Jy -aXZBNmkzRzIvWTZFTFBnTE1KKzAwWCtWbGQzclJIejdmaXR3NVJoQUhqWEd1 -OFYyYURqU2dZM29jNFZyNGV6LzFsbUpWWGtBMU9hTFltWEhCSWhxbllmUUpq -bnB6ZFRMSzhQL1p5aUNyMGFHUEU3VXRTZHlkYTFIQnFsWmY5elNNUHQ0bmN6 -VWp6S0x3OVNMSEpZdUgrSEtQN1FtczdoTE9Ld0o5SVNyRlNJUlZMRVhSeHdD -UkY0R2IxTDR3UTRub3ZhS1BCbXQ3NGlwN2piRXZqV2NZSkZDSWFYRkcrN0Uz -a1kyTjJOQjNyVHd0OWI1anVweW5JVWZyVUdyZ3M0dDhjendqSG1LNU9KYzRV -RGxvbGE5NDZBWlFYWFRSWWwxNWhjbWgzK1lyUHhFQVdrak9QS3gvWjZ3SGhw -M2ZpY2poQ3dRdmpUeTliL1d0VERWRWU1blB6TXFpQU81aUhhMGxOSjdEMkpG -aERPaHY5ZEFORDRtdlNCTCtOTlBQcUdFaHQxZGZtYm1YS3lJWjF4Y1JPVE5t -QVhjU3ZlYnpVTkRNOGp5SEhwNlYrSTd2dHR0VHAzYmlhNnBRTXIraG82NUx1 -RldsVVdwa2U2Um5wbUdVWHhHd25xSGw2Q2hkMWU1aGFHVGlBTXN0dDVONTlo -THlIN25BTFplNVd1c3pOQ1ZMQlkrbFNadlZINkcyZStmTlpsNmpDMlZ0Mkhx -c21CSVVJVlVsTVAzZ0phb1pEK0RQQUxib1ZHdC8xMTgzQUZFYVZxcHJ3cE9M -ak1wQnBTWmdKWkU2TCtCbnk4dUh1VFNxank2RE1jeTdES3dKY0tNWGNsdzRu -eFRRUVJPaUtoL1RZaUZiYVZhVjBXY1oxSFQwOWJWczYzNlVXbzJjdE5hNzdX -SFFNNHVabElMQm0yNUpPZDJzTDA0NVhTS0c0ZUlxZ1I0SE1jQmZJTHdpb3gr -OC8vb1QrR3NraCtVbm50cGYrS3gyV3h1U0E4Q0M3d0hFM2JNSE05alRpYWda -MU95RGs3Z1FOdGZpS3B1SWlwdGNwL2VtUmE4M3VURTBVeXhhZm9RZHNDbExp -dkk1YUdsTGRtTG5CYVFUSEZNZFR6ZHRteDBYVkt6SUltbXhNamRnek9lSGE2 -VUpzMnRZcHU2YjhhY045cDUwSUh1M242RTNIeFBURmFqZTFTM3ZhWkRicVZQ -bmlqclZWaVA5bUdnRWxBVitkMUJSeG54amROdTRsUTVaNVVHOUFuS2txenpt -R2Y2V3hIRG1uSEJyajAvb29EZGJnZHNRdTl0MjNMc0lPeSttd3dNTWk5VmEy -STBOMHgxY1RvU2ZFQmRrb09JVGIxZVE3LzQ0TjBESmoxTWJHbklrUkNHSThY -Y1QrZXpKbkxrcjZpQ0h1UXlycnpLbmIrTVRQbS9zWVN3bllXWVFnVzc2d2tk -cGVWMzR6YXFDdGNjWjF0M1BPV3VINC8zbmUzZmQwRloxNTIxYWp0M1owL2d0 -emk1bjQwVmhpdDFsekFJQmZ2eXNOVWcwVXpJU0xsV2h5RDlYZkVLaTZWNDZs -NUQ4ci93VVhUZlUwcGJpRWE1eTBJSk8wa2FkOWZXa1JlWVBhbFZMNUdxblZS -L1NrYWhyb3ZPcUJtVkplOFNONXpOUkU3ck9SZDBHN2J3bWorVDVwdHNmdFZN -NDduQnREZVhscW9IaEg3Ym14UDcxbFV4M1Y4VUJrcE9PeHdwRFpHM3RUVlFp -UERQWFJWdFkwakVDWnhKWTNha21YQnFKUWZLanQrU2xBOU00UGg1QStRWWxF -cm9yQlZkK1EzSzlVd1djcXhGaFRSRmEwRWx5WlI1K2VtTFFqQUE1S1NUdmlh -U0hsVnRaQWdaS1I5REZLWVFFUkQ1VjNKNVUrdVZUVldOdmMzSDVXVEVqS2Zr -eFl0V2k3azJTTHQ2R3JCaDZtK1BaYzQ4RTRSU0pJRzNJQjZKVGFOSnRSUzEx -REVtamlKYWI1em5PYUdiVU9SMVdVRitXRzRSYTlvSndCTUs4SU9aSzNRZzdQ -VmRRRHYwUFc3dTduY0VIa3hFU1NzdEtYY3o4OU5RdmgzenFUWXVYTjB6MlNJ -eERXK0R2SjBPaGpYM3JjalFWeDZJU2o2R0hvdzJtVUpZdVAzN09uTlFiK2JX -bkMvWWFMaStUa0tGL2Q4dGZiMnNETWFtVHNoOFpGSXgwNVZMTGxFQW5DWEJX -eE1hQUx3MjA4Y0FCM2tSMVVBdFZnb0RXR3grYWRzY3YwYStrTFEyL2VSR2JB -bE1VaFAzRy9ZYnhwL2s2Zm5KeHlNaVZqbnFPL2Q0NXF2T1hkTWprVmw3WHRI -M3k5MDZ1TEVxVTJMc3VPanJwTEFTTVV0Z1NZZEVrTkFCbVJjYy90WlB6dmJD -bHliRGMwazFGcFVtbHM2N0JHSzk5UEFXSE9NZTJ3clg1ZzA3TWE0SWtQKzIz -eDU2YVg4LzlGV05Vam5Kcld4cGtndnFOek1PNmorSFhNUE5WZkY5QVFZblQv -bG5YWlU1cm9uajdLSmtIUElaWmlkSnF2V2tjVURwOFZzdm9VRm41SGcyMit3 -UzdOamhYVFlJZU51S2ZPanNOVjFkOU1hWU9TeE9iR1lGR2RRTkdGOVh0RHlT -ZXR1emdtWmg0WHp6OTM5d1NMbEk5TGE4OEoydnV1cVlMUkFuL05xTVY1bU5n -WlU4WXJSQmlJZmdwRmZUWldGT0MvM050ZDkybkVyaUtSWmJITWdBdmpaSldT -VGh2V2piZTlCREpiZHd6MmVsdUJtYlluOWg4Vk1idlkwQUU4Mmowb0laMDJB -REhLc1JubXAvcEJIR1JxdkduVG9jMXJ1c3dMZmZCZzBtd0ZienV4dUhjQ0xY -K0xCSzBOaTNZMTUzVktmSHNYMWc3WU1WdGF1YStoK0ZmMFc4WHdzL052QjY3 -ZkZlakNzNU95VXpvd1V0ZlJjVmZxZTFGaWt2TW54ZmN0UmVUbnp6Rm5rWjRt -WTVLYS9laDJudTN4bEFiUGt4K0FRWDEyRFlqQnQvaWhDSTdLWDhGaFhKeG0z -SXc1aGpIanlmc0FYSyttU0F0L3NjZUcyNmlQQllpZEx2aXVtZ25Na0dnakZy -UGJ0U1gvZUgybThiYW9sUVQzWkxZT3duOW91a2NJc0ZmYzhDeXlhU2lnYzQ4 -TFBGemJJM1NZSGQyMktwSjVaL0ZvK1d2eDhMYkx5b2FBMVp3Qk5SRTh6RjBG -WmhBa2lKb3VCNXU2dng2TDhVRExLTWIxVnlOVW9sZVdoS3RFNm9KRUt3VTRP -a1VMNk5BSHVrVGt0Wi9oTU1lT3FnaGgwcG5Ma1VZVERDNXRuWE9QRGFCQnhw -UUFGSnVSQXhRbUI3cElBMFpVblJKT0xYRWJOdjRHWGNGdjFGU2RwYUZRaEtz -QzVybDhsTGR5VkRFOXJKTllqYUhhdU4vZ0NoT2llc0QrT2FjU0NYV2h2cU10 -bGtDMXZVZkhTSmM0NDA0R1c1L2xNa3RTRWFHNWV5OExkU1A5QTlyOGlUc1ZR -RFNhZU11NXJXSFN4ZkFicytXV045Rm1RVkN3SEs5Vyt5aXlMd0YzUjFQYlhK -MmdWMUFGM2xsSUR0WUlzWjBsZlRCMWY0ai9TNDdzLzJZblV4MVNuV0l5a2Z6 -ODN3RHJDaU5KdkMwRmJ6b09lZlkvdzJqdUM5RzVDNTZtdllLR0h5Uk9nMGI3 -NkYzQ0NmTHVTdlY1eDlFZ0crVnhLQk94WUw1Ykpya2lEYkNaWFJua1IxdWtC -Y0tFTXA5dWZJY21hU2NxRWpqSG9SM214OXNpcEJTYVZQKzJabTFCOVlubTFV -N1VVTXpwUDhUNXorWjV3bzh1cGVmdklNVzRnVVJnRDlBVWRWaG5xc3ZnL0tR -OGVFRDVKbXBSQjNETkJoK0Y2YXU0cHBhZVdpYUVkSWI4UldWcm1FY0EySU5R -UFJFd3F0WDQwZDFldGJ5LytzTEtaeFFsYWlNQy9mZlFZdVJhL0tHdmZZS0c5 -UkZGdG1uQjAvZ2JBdjZVcWlIQXlwbEhOZW9XcmJFM3N1WTFIUFZXU28rZzRS -Y0IwMzJmUDJaOW02SFJocXBtU2w1eUVaMENLYjBkVDdmdS9SUzZVLzNIYTcz -Z1FKY0hzdnU3Y2E1U05LdU5LclR0NEl6dGdsWldlejl5NG92OXFFeU9Oc05v -RUdFUHUwWk4zMEQxMDBxemlGYlM2dHR3dzZ1d2lFUExRZ3pycXdtanlRWFhr -b21WekhLc2laajBYdEdhWG9Nc1NXd1hLczlIMmZzeXpCVmQ2b1lwakJwQVNn -Wkp6N0lLNFVQaVUrNHpObjluYUZsejk3RGhkN3RvWVpISHJDb2dvdkFTOTBn -VENBSFhRQXhYcm1FMEVxRDNsMWxVMUJJTXY1L01BWnJLeEVXejQxT0dtaEtk -enFxRElzSVJBV3Zwck92ZWJrN2lzQnlxZ2ZnWDZaU29KaStzTnRhL3FTQ08y -aUpoVStiS2hjcDNJNzVydCtMUlhUUUs5VkNEUFhNTS93bE91UTVES2c5SHpa -K2tlVjNUSVQrdWpwUUZ4SnUyUVNpeTRCUU5tbEpyNTcxRExqOUppekFRYXBZ -QkUzK1RsNm11bUlydkJWalN2bm8zOHZWWHpSKysrbHNqeS9iVjdvaDRZQUU3 -c1pMUzl1RkhmM0pnc0pOK2FOTWlhczZpZnRmV05BaEY1VUx3b3hSTmV4MUNz -UGVNTWY3T3RqekdMUXIyTzVBejJsMDhXb0JjZjJHM3AwUVlYL05IVlUwYUMr -U0ZhY05pTGZVZ1Q5UnBYQ1FUb1dRQ2xaem15UTc2RGRHSHJWWUlFTDBVblpG -UnRZS0Jrbmo2ZG9SOGRQWEhybEdwV1JRNkRDV2E2SmxqQ1ZydklEcUZKdmJV -TXk2MXFZUjVJb01sRmNWMUY2QU5aSU12SGhYUy9aWHFrb3pKNnRXZFB3THdK -cVpQUGVTV2x0cm80bDkzOGR5RmtPZEM5NkNLRFVvaHBEY0pxWXh2NnJtUDZj -RlkzQWllYmN5K080c3E3YkhvcUlDK2pXK25zSms3aWdIUTJIdHQzMHAvQkM4 -Yko1M3RLS0lHYzRCYzFPajR0YWl2V2ZXcHV3S1NlMnh6WE50eEFrYmw1OEEx -MWxkL3RBNGhVNG1oYkNHQVBpK3ZGelNzWU9DL2Z1K0wxSGpiSFF2ajJ4ckNZ -THZ2MTRBOGN0N2NBL3pGelFJRmJaUHg2Y1BQbVhWWk8rZmwvZ1p2Q3lNaDBh -ZncrZWlBbXpSRGsvaTdsTjNiQUtWWjdPYWgvMDVHcnNCV1JPSGlodWsxTXhr -R1FodmdNSVA5RVNCRzJaTWdTZ0dvMFVFZjZINkYxbzVzQUp1eko4bTNjeDNJ -OUlzcld1bHFzK3I4cm1MTjVYZ2Q0WGF5WklwWCs2cWR6QzJDN3UzcWVJMkl1 -Y2xWUTFyWm9PMjZZL2RqQWtRY0ZSN09Oc2tTaHF3MnVITEZCRXJkQnVxU0RF -eHc5bHNOYUdqYkpqOXpXWmZPRy9lclJDcW9VV3FpVWhLczg5M2hjYUJFWlM3 -aHI4VzhMaWNHMHRyWVBYeUFKR0FEVmtUVUxLdE1DcUJJc010bnN2NVlibm9K -aVI0MHM4THpLcldtMnMzWUNOQVFpMEcwUTROdjVoOXF3WlhlaWxtZ3I1bi9u -eUEyRitrTzVYTVlaaFhJMWlmZ2xIRG4wMkExUzYydkxvaWlVcGl1V1ptV2lT -V2tBOTAyenBvWTQra1dnYTZDVDdSamhUY29DWG90eENUWGNVWC9DM1hWMnZw -MXNyb0tlODBUbHZXd3BSY2VGeEc3RVF5N3crdGxEVWNUb1lDdVZ0b1NhZTZQ -d0FFdUszSC9rZzR6dGoxcXc1STZncG9LcFhIai9wWlpnbzNFeGlsdTZkdEFK -ZzFGU1I3aVVhblZWeWxobXhDRWUrSmUyQXR4N2Z5UHRkRHRsTUZ6ZDFMN282 -aHVaMmJPY1FtZHNMWFJMSVh0cWdabDZMd01iTkZETCtIcDIrNGJRWU9TczZj -Q0QvNHdKUHJpWVZKSjdhWjltVEhSdDU1ZUkzR1c5K3l6eVF6dUZobTJYTWdz -QVlwL0I3dTluOWhXK1IrUWhPMjRjUnYyYnhoYzZKaVc4MmNTbFp4aEJxL25B -SHZVdTQrQWV0K2FLWTY2V0VnZVhnSG9idWVMaEs0bFlxYTRRWUVGRFJFWGMv -NldZRjc3Unk2dUZTekVxaDdwSDhOQklQL3FUbzdtR2Nab2FkZXk0TVNKV3Yz -T2trbUZ6bi9VdGVZSC9UNURkSjhBck4yL0JJSlNjUTBoUk9ZUStLa3F2dXVZ -ZW11Zlp5QU1GeGRIU3RRTUJaTEMxcHF3MEF1aks2cTdkTWpFRUM3d0M3YWtH -dVVGaGgzdjFFTXQ2L2VONlpNZ2tObHU3NHg1SEJENU50RnFXcCtuRXBJSTJa -U1ZMTnoyeWtMNjB0Y1pTTUhiZkh3dEF3Q201bmwyYS9yT1hOMDJvdHg1bnly -Vk5EWldPejAxNEVveGh3enRFTTM1NW4zR2pZOTFjVEtjbGFTc2NCblJUUG91 -dnFNOW1nRFAxeitMR0JCclBLdzdneE1zUDBvZzkxOGlkTGkwZWxiL3M0QTRV -UVJmN0dWUml5L3hUWXM3VUplSjI1RzIzK2ZpeTNJSlBxQ1JrKzlPY2JneFF4 -UlQ1SHZUd1Q2NGZPT1BhdFhuZFZwZDZ4VFBlSG1TamFuQW94TTlMYWR5V2Uy -M1QxcmFTWnlSOFhrWUIxUzVDUTlvU0xQK25sQ0thSHNtNjA0eHdPQ2ZmTlg5 -QUtTVVVnZE45T1VLWGhWK3pvbzVkN3FUK0UwR1crREZCWnMrN3FBdS92YUl0 -Rkdzem5IOE1vRUNzSFdtWGhuTFVDNHJKcmNIdTYrRTlsZlp2ckVXVE5vM081 -UFF3OEdCSndUVWtsTDFTQlJiWUdRd3czZFJpQzlQV0ZWOFdYMXhuS2ZHOE5P -WnJRRll1d29uQ3dHWXI3UVhsQVU5NWRsREpCZG5za3hyM2hsYVdDT2hlYUYv -Q2ZjeHhZQ2tVTVFSYzdSWHhnSlpmbjBQZzgzV2d5T1pKSVZNQ1FueDNhMkJF -T21YWk81cHZQSHZlU0JBWlNlbHR2amN6VkFnSFFyN2RTNG53TWh0Wjl4ZUZ4 -TDZnZDlFYXFqSVFrUnMvZ1dSREhQSU5iU2VlRmNyQWc3YjNjK0lmcElMWkdM -VG5jV2ZmWVEwSmgxYUJicEhVWG8yWjdWWjVOU3lhVFp4QWVNSkhaOThraVh4 -S09hUGVjOWk3TmF2UWtrVlZMaHNFbU9RZW9EOGZ1R2RuR3orN3FoYU9yZ2dT -d1picFEzV3ZsdFNYRVZhVHhKQ0RyTnNHc2RBc05sZHJ3UTV5ZHFhNXIxSzlI -NDQxZUFtakRhNk8vTFQwbjV0YkpEYkF5NGpKVDhwMUpyQXpsK1duQXNCbEc0 -U2dOQlBzTk00OTVIS3h5SnE2aWRobDhjQmN4RXFzTmxuQkVIS0JFYjhMTjZM -SVFLa2lQZTVOMjJsNlpyeFB2K3oxNjFsTHMwTmowTDVGMmRqbTB0MDFVZGdm -ZWlFV1Z0WFZDSk1hbGJvZnNoU2pvVWE4K1VUSzBTMytKOWFZNWJESEtLYUdC -ZVJjSmdmaXprOG9JTWlpalZmNFNlQUhzRDBPRHhBeXlpb1VKWTYxME9ZZ0d1 -NUh2KzVwcWMzYUNsRnFtcnFSNGoxNzNSLzY3MVpURGNhOHFOTldTTm1FbTFa -NmFzOWFPZ2oxRWRiM0lvMjRvR1djbnc1SkhvUmVMMzE5SVhreHozdktERkM5 -RWUwRWsyRGlMK0h0QlMrTCtEY1k3VGdTYXB5TDk5emluVjhPbkxFWjNnTzNL -V3RObEM2bDZEN1ZiTzBrdThNR241TERPTFRpbnNyWHpaZXhCWGZSNExpY0JM -ZnJ6Y1BYYXo2ZDVYZkVSSUk5ZEJGUGdxM3BaQUt5elljV0tBL05tSGw2RGJM -aDFhWHhMdTlmcURsQUlhUEhBbnlEbjFHb1F3SU41UEFITmh5TXJsQUg0U1FS -TlBEcExwRGgyTFJldzRPdFpTUFpMSWZaYnZlSnRsd3VkQmEvbTMyTEprSmZx -elFFK21WQk5jVjNSNG9VSlVPREgxcnQ0N1hRRHJzb3dXd3o5TUpzWS96bXFm -RDh1bC55MU9sc1hoUklmUzJxZXo0LlZoWUFWWFBrdTREY2Z2RnNEZWdpelE9 -PSIsInNpZyI6InN4enMzcnEzaEhnTnFJODQ5T05ZS3p4MUNDRGhBdjgzSGhY -SVRLWFR0ZlNLL0k0UlBxR0RubHFKZFVzQzBNTFUwU0w3eWNUd0xrTnoyS284 -UTdMZEFRPT0iLCJhbGciOiJhZXMtMjU2LWdjbStlZDI1NTE5In0= ------END LICENSE FILE----- +version https://git-lfs.github.com/spec/v1 +oid sha256:962ef8bda42d71e14dfdee5c643ca24758b0d175ff8e68fdd7bd9680f9d815a1 +size 13956 diff --git a/spec/matchers/allocate_less_than_spec.rb b/spec/matchers/allocate_less_than_spec.rb new file mode 100644 index 0000000000..9f2b35e3df --- /dev/null +++ b/spec/matchers/allocate_less_than_spec.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'rails_helper' +require 'spec_helper' + +describe :allocate_less_than do + let!(:stream) { StringIO.new(SecureRandom.bytes(50.megabytes)) } + + it 'should pass when allocations are under limit' do + expect { stream.read(1.megabyte - 1.kilobyte) }.to allocate_less_than(1.megabyte) + end + + it 'should fail when allocations are over limit' do + expect { stream.read(1.megabyte + 1.kilobyte) }.to allocate_at_least(1.megabyte) + end + + it 'should pass when chunk size is under the limit' do + expect { + while chunk = stream.read(512.kilobytes) + chunk + end + }.to allocate_less_than(2.megabytes) + end + + it 'should fail when chunk accum exceeds the limit' do + expect { + accum = +'' # retain all chunks + + while chunk = stream.read(512.kilobytes) + accum << chunk + end + + accum + }.to allocate_at_least(50.megabytes) + end + + it 'should fail when chunk size exceeds the limit' do + expect { + while chunk = stream.read(25.megabytes) + chunk + end + }.to allocate_at_least(25.megabytes) + end +end diff --git a/spec/matchers/deep_include_matcher_spec.rb b/spec/matchers/deep_include_spec.rb similarity index 100% rename from spec/matchers/deep_include_matcher_spec.rb rename to spec/matchers/deep_include_spec.rb diff --git a/spec/support/matchers/memory_matchers.rb b/spec/support/matchers/memory_matchers.rb new file mode 100644 index 0000000000..cf91e12fef --- /dev/null +++ b/spec/support/matchers/memory_matchers.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'memory_profiler' + +RSpec::Matchers.define :allocate_less_than do |bytes| + supports_block_expectations + + match do |block| + @expected = bytes.to_i + + report = MemoryProfiler.report(ignore_files: /rspec/) do + # NOTE(ezekg) reenable GC because profiler disables it but we want + # to measure memory consumption under normal load + GC.enable + + block.call + end + + @actual = report.total_allocated_memsize.to_i + + @actual < @expected + end + + failure_message do + "Expected block to allocate less than #{@expected.to_fs(:delimited)} byte(s), but allocated #{@actual.to_fs(:delimited)} byte(s)" + end + + failure_message_when_negated do + "Expected block to allocate at least #{@expected.to_fs(:delimited)} byte(s), but allocated #{@actual.to_fs(:delimited)} byte(s)" + end +end + +RSpec::Matchers.define_negated_matcher :allocate_at_least, :allocate_less_than diff --git a/spec/workers/process_npm_package_worker_spec.rb b/spec/workers/process_npm_package_worker_spec.rb index a158044f97..12db7aa01f 100644 --- a/spec/workers/process_npm_package_worker_spec.rb +++ b/spec/workers/process_npm_package_worker_spec.rb @@ -249,4 +249,23 @@ end end end + + context 'when artifact filesize is unaccurate' do + let(:artifact) { create(:artifact, :processing, filesize: 1.kilobyte, account:) } + let(:file) { file_fixture('large.tar.gz').open } + + before do + Aws.config = { s3: { stub_responses: { get_object: [{ body: file }] } } } + end + + it 'should not process file' do + expect { subject.perform_async(artifact.id) }.to not_change { artifact.reload.manifest } + + expect(artifact.status).to eq 'FAILED' + end + + it 'should be efficient' do + expect { subject.perform_async(artifact.id) }.to allocate_less_than(1.megabyte) + end + end end