| #!/usr/bin/python |
| # |
| # Copyright 2015 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import codecs |
| import copy |
| import credits_updater as cu |
| import os |
| import string |
| import unittest |
| |
| # Assumes this script is in ffmpeg/chromium/scripts/ |
| SOURCE_DIR = os.path.join( |
| os.path.dirname(os.path.abspath(__file__)), os.path.pardir, os.path.pardir) |
| OUTPUT_FILE = 'CREDITS.testing' |
| |
| # Expected credits for swresample.h applied with the rot13 encoding. Otherwise |
| # license scanners get confused about the license of this file. |
| SWRESAMPLE_H_LICENSE_ROT_13 = """yvofjerfnzcyr/fjerfnzcyr.u |
| |
| Pbclevtug (P) 2011-2013 Zvpunry Avrqreznlre (zvpunryav@tzk.ng) |
| |
| Guvf svyr vf cneg bs yvofjerfnzcyr |
| |
| yvofjerfnzcyr vf serr fbsgjner; lbh pna erqvfgevohgr vg naq/be |
| zbqvsl vg haqre gur grezf bs gur TAH Yrffre Trareny Choyvp |
| Yvprafr nf choyvfurq ol gur Serr Fbsgjner Sbhaqngvba; rvgure |
| irefvba 2.1 bs gur Yvprafr, be (ng lbhe bcgvba) nal yngre irefvba. |
| |
| yvofjerfnzcyr vf qvfgevohgrq va gur ubcr gung vg jvyy or hfrshy, |
| ohg JVGUBHG NAL JNEENAGL; jvgubhg rira gur vzcyvrq jneenagl bs |
| ZREPUNAGNOVYVGL be SVGARFF SBE N CNEGVPHYNE CHECBFR. Frr gur TAH |
| Yrffre Trareny Choyvp Yvprafr sbe zber qrgnvyf. |
| |
| Lbh fubhyq unir erprvirq n pbcl bs gur TAH Yrffre Trareny Choyvp |
| Yvprafr nybat jvgu yvofjerfnzcyr; vs abg, jevgr gb gur Serr Fbsgjner |
| Sbhaqngvba, Vap., 51 Senaxyva Fgerrg, Svsgu Sybbe, Obfgba, ZN 02110-1301 HFN""" |
| |
| # The real expected credits for swresample.h. |
| SWRESAMPLE_H_LICENSE = codecs.decode(SWRESAMPLE_H_LICENSE_ROT_13, 'rot13') |
| |
| |
| def NewCreditsUpdater(): |
| return cu.CreditsUpdater(SOURCE_DIR, OUTPUT_FILE) |
| |
| |
| class CreditsUpdaterUnittest(unittest.TestCase): |
| |
| def tearDown(self): |
| # Cleanup the testing output file |
| test_credits = os.path.join(SOURCE_DIR, OUTPUT_FILE) |
| if os.path.exists(test_credits): |
| os.remove(test_credits) |
| |
| def testNoFiles(self): |
| # Write credits without processing any files. |
| NewCreditsUpdater().WriteCredits() |
| |
| # Credits should *always* have LICENSE.md followed by full LGPL text. |
| expected_lines = NormalizeNewLines(GetLicenseMdLines() + |
| GetSeparatorLines() + |
| GetLicenseLines(cu.License.LGPL)) |
| credits_lines = ReadCreditsLines() |
| self.assertEqual(expected_lines, credits_lines) |
| |
| def testLPGLFiles(self): |
| # Process two known LGPL files |
| updater = NewCreditsUpdater() |
| updater.ProcessFile('libavformat/mp3dec.c') |
| updater.ProcessFile('libavformat/mp3enc.c') |
| updater.WriteCredits() |
| |
| # Expect output to have just LGPL text (once) preceded by LICENSE.md |
| expected_lines = NormalizeNewLines(GetLicenseMdLines() + |
| GetSeparatorLines() + |
| GetLicenseLines(cu.License.LGPL)) |
| credits_lines = ReadCreditsLines() |
| self.assertEqual(expected_lines, credits_lines) |
| |
| def testKnownBucketFiles(self): |
| # Process some JPEG and MIPS files. |
| updater = NewCreditsUpdater() |
| updater.ProcessFile('libavcodec/jfdctfst.c') |
| updater.ProcessFile('libavutil/mips/float_dsp_mips.c') |
| updater.WriteCredits() |
| |
| # Expected output to have JPEG and MIPS text in addition to the typical LGPL |
| # and LICENSE.md header. JPEG should appear before MIPS because known |
| # buckets will be printed in alphabetical order. |
| expected_lines = NormalizeNewLines( |
| GetLicenseMdLines() + GetSeparatorLines() + |
| ['libavcodec/jfdctfst.c\n\n'] + GetLicenseLines(cu.License.JPEG) + |
| GetSeparatorLines() + ['libavutil/mips/float_dsp_mips.c\n\n'] + |
| GetLicenseLines(cu.License.MIPS) + GetSeparatorLines() + |
| GetLicenseLines(cu.License.LGPL)) |
| credits_lines = ReadCreditsLines() |
| self.assertEqual(expected_lines, credits_lines) |
| |
| def testGeneratedAndKnownLicences(self): |
| # Process a file that doesn't fall into a known bucket (e.g. the license |
| # header for this file is unique). Also process a known bucket file. |
| updater = NewCreditsUpdater() |
| updater.ProcessFile('libswresample/swresample.h') |
| updater.ProcessFile('libavutil/mips/float_dsp_mips.c') |
| updater.WriteCredits() |
| |
| # Expect output to put swresample.h header first, followed by MIPS. |
| expected_lines = NormalizeNewLines( |
| GetLicenseMdLines() + GetSeparatorLines() + |
| SWRESAMPLE_H_LICENSE.splitlines(True) + GetSeparatorLines() + |
| ['libavutil/mips/float_dsp_mips.c\n\n'] + |
| GetLicenseLines(cu.License.MIPS) + GetSeparatorLines() + |
| GetLicenseLines(cu.License.LGPL)) |
| credits_lines = ReadCreditsLines() |
| self.assertEqual(expected_lines, credits_lines) |
| |
| def testGeneratedLicencesOrder(self): |
| # Process files that do not fall into a known bucket and assert that their |
| # licenses are listed in alphabetical order of the file names. |
| files = [ |
| 'libswresample/swresample.h', |
| 'libavcodec/arm/jrevdct_arm.S', |
| 'libavcodec/mips/celp_math_mips.c', |
| 'libavcodec/mips/acelp_vectors_mips.c', |
| 'libavformat/oggparsetheora.c', |
| 'libavcodec/x86/xvididct.asm', |
| ] |
| updater = NewCreditsUpdater() |
| for f in files: |
| updater.ProcessFile(f) |
| updater.WriteCredits() |
| |
| credits = ''.join(ReadCreditsLines()) |
| current_offset = 0 |
| for f in sorted(files): |
| i = string.find(credits, f, current_offset) |
| if i == -1: |
| self.fail("Failed to find %s starting at offset %s of content:\n%s" % |
| (f, current_offset, credits)) |
| current_offset = i + len(f) |
| |
| |
| def testKnownFileDigestChange(self): |
| updater = NewCreditsUpdater() |
| |
| # Choose a known file. |
| known_file = os.path.join('libavformat', 'oggparseogm.c') |
| self.assertTrue(known_file in updater.known_file_map) |
| |
| # Show file processing works without raising SystemExit. |
| updater.ProcessFile(known_file) |
| |
| # Alter the license digest for this file to simulate a change to the |
| # license header. |
| orig_file_info = updater.known_file_map[known_file] |
| altered_file_info = cu.FileInfo(cu.License.LGPL, |
| 'chris' + orig_file_info.license_digest[5:]) |
| updater.known_file_map[known_file] = altered_file_info |
| |
| # Verify digest mismatch triggers SystemExit. |
| with self.assertRaises(SystemExit): |
| updater.ProcessFile(known_file) |
| |
| |
| # Globals to cache the text of static files once read. |
| g_license_md_lines = [] |
| g_license_lines = {} |
| |
| |
| def ReadCreditsLines(): |
| with open(os.path.join(SOURCE_DIR, OUTPUT_FILE)) as test_credits: |
| return test_credits.readlines() |
| |
| |
| def GetLicenseMdLines(): |
| global g_license_md_lines |
| if not len(g_license_md_lines): |
| with open(os.path.join(SOURCE_DIR, cu.UPSTREAM_LICENSEMD)) as license_md: |
| g_license_md_lines = license_md.readlines() |
| return g_license_md_lines |
| |
| |
| def GetLicenseLines(license_file): |
| if not license_file in g_license_lines: |
| g_license_lines[license_file] = GetFileLines( |
| os.path.join(cu.LICENSE_TEXTS[license_file])) |
| return g_license_lines[license_file] |
| |
| |
| def GetFileLines(file_path): |
| with open(file_path) as open_file: |
| return open_file.readlines() |
| |
| |
| def GetSeparatorLines(): |
| # Pass True to preserve \n chars in the return. |
| return cu.LICENSE_SEPARATOR.splitlines(True) |
| |
| |
| # Combine into a string then split back out to a list. This is important for |
| # making constructed expectations match the credits read from a file. E.g. |
| # input: ['foo', '\n', 'bar'] |
| # return: ['foo\n', 'bar'] |
| # Comparing lists line by line makes for much better diffs when things go wrong. |
| |
| |
| def NormalizeNewLines(lines): |
| return ''.join(lines).splitlines(True) |
| |
| |
| if __name__ == '__main__': |
| unittest.main() |