diff options
author | Bjoern Tropf <asym@gentoo.org> | 2009-10-31 12:52:36 +0100 |
---|---|---|
committer | Bjoern Tropf <asym@gentoo.org> | 2009-10-31 12:52:36 +0100 |
commit | 63d063d03127573225e1c43d0d9e03e5c7884d21 (patch) | |
tree | f1eb27680c808e5e69f520a545d1f1a64d7e8fe6 /tools | |
parent | Code cleanup (diff) | |
download | kernel-check-63d063d03127573225e1c43d0d9e03e5c7884d21.tar.gz kernel-check-63d063d03127573225e1c43d0d9e03e5c7884d21.tar.bz2 kernel-check-63d063d03127573225e1c43d0d9e03e5c7884d21.zip |
Large restructuration
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/cron.py | 405 | ||||
-rwxr-xr-x | tools/findcommit.sh | 62 | ||||
-rwxr-xr-x | tools/testsuite.py | 212 |
3 files changed, 679 insertions, 0 deletions
diff --git a/tools/cron.py b/tools/cron.py new file mode 100755 index 0000000..01e04af --- /dev/null +++ b/tools/cron.py @@ -0,0 +1,405 @@ +#!/usr/bin/env python +# kernel-check -- Kernel security information +# Copyright 2009-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from contextlib import closing +import xml.etree.cElementTree as et +import cStringIO +import datetime +import logging +import mmap +import os +import portage +import re +import sys +import time +import urllib + + +class CronError(Exception): + def __init__(self, value): + self.value = value + +NOCVE = 'GENERIC-MAP-NOMATCH' +NOCVEDESC = 'This GENERIC identifier is not specific to any vulnerability. '\ + 'GENERIC-MAP-NOMATCH is used by products, databases, and ' \ + 'services to specify when a particular vulnerability element ' \ + 'does not map to a corresponding CVE entry.' +DELAY = 0.2 +SKIP = True +MINYEAR = 2002 +MAXYEAR = 2020 +NVDURL = 'http://nvd.nist.gov/' +BZURL = 'https://bugs.gentoo.org/' +STATE = ['NEW', 'ASSIGNED', 'REOPENED', 'RESOLVED', 'VERIFIED', 'CLOSED'] +RESOLUTION = ['FIXED', 'LATER', 'TEST-REQUEST', 'UPSTREAM', '---'] +BUGORDER = ['bugid', 'reporter', 'reported', 'status', 'arch', 'affected'] +CVEORDER = ['cve', 'published', 'desc', 'severity', 'vector', 'score', 'refs'] +FILEPATH = os.path.dirname(os.path.realpath(__file__)) +PORTDIR = portage.settings['PORTDIR'] +LOGFILE = None #os.path.join(FILEPATH, 'cron.log') +DIR = { + 'tmp' : os.path.join(FILEPATH, 'tmp'), + 'out' : os.path.join(PORTDIR, 'metadata', 'kernel'), + 'bug' : os.path.join(FILEPATH, 'tmp', 'bug'), + 'nvd' : os.path.join(FILEPATH, 'tmp', 'nvd') +} +REGEX = { + 'bugzilla' : re.compile(r'(?<=bug.cgi\?id=)\d*'), + 'grp_all' : re.compile(r'(?<=\()[ (]*CVE-(\d{4})' \ + r'([-,(){}|, \d]+)(?=\))'), + 'm_nomatch' : re.compile(r'.*GENERIC-MAP-NOMATCH.*'), + 'grp_split' : re.compile(r'(?<=\D)(\d{4})(?=\D|$)'), + 'wb_match' : re.compile(r'\s*\[\s*([^ +<=>]+)\s*([' \ + r'<=>]{1,2})\s*([^ <=>\]]+' \ + r')\s*(?:([<=>]{1,2})\s*([' \ + r'^ \]]+))?\s*\]\s*(.*)'), + 'wb_version' : re.compile(r'^(?:\d{1,2}\.){0,3}\d{1,2}' \ + r'(?:[-_](?:r|rc)?\d{1,2})*$') +} +CVES = dict() +logging.basicConfig(format='[%(asctime)s] %(levelname)-6s : %(message)s', + datefmt='%H:%M:%S', filename=LOGFILE, level=logging.DEBUG) + + +def main(argv): + 'Main function' + + logging.info('Running cron...') + + current_year = datetime.datetime.now().year + if current_year < MINYEAR or current_year > MAXYEAR: + current_year = MAXYEAR + + for directory in DIR: + if not os.path.isdir(DIR[directory]): + os.makedirs(DIR[directory]) + + logging.info('Receiving the latest xml file from the nvd') + + receive_file(DIR['nvd'], [NVDURL, 'download/'],'nvdcve-recent.xml') + + if not SKIP: + logging.info('Receiving earlier xml files from the nvd') + + for year in xrange(MINYEAR, current_year + 1): + receive_file(DIR['nvd'], [NVDURL, 'download/'], + 'nvdcve-%s.xml' % str(year)) + + logging.info('Receiving the kernel vulnerability list from bugzilla') + + url = [BZURL, 'buglist.cgi?query_format=advanced&component=Kernel'] + + for item in STATE: + url.append('&bug_status=' + item) + for item in RESOLUTION: + url.append('&resolution=' + item) + url.append('#') + + receive_file(DIR['tmp'], url, 'bugzilla.xml') + + filename = os.path.join(DIR['tmp'], 'bugzilla.xml') + with open(filename, 'r+') as buglist_file: + memory_map = mmap.mmap(buglist_file.fileno(), 0) + buglist = REGEX['bugzilla'].findall(memory_map.read(-1)) + + logging.info('Found %i kernel vulnerabilities' % len(buglist)) + + logging.info('Creating the nvd dictionary') + nvd_dict = parse_nvd_dict(DIR['nvd']) + + logging.info('Creating the xml files') + + created_files = 0 + for item in buglist: + try: + receive_file(DIR['bug'], [BZURL, 'show_bug.cgi?ctype=xml&id='], + item) + + vul = parse_bugzilla_dict(DIR['bug'], item) + + for cve in vul['cvelist']: + if cve == NOCVE: + vul['cves'] = [NOCVE] + break; #TODO + else: + try: + vul['cves'].append(nvd_dict[cve]) + except KeyError: + raise CronError('No Nvd entry: ' + cve) + + write_cve_file(DIR['out'], vul) + created_files += 1 + time.sleep(DELAY) + + except CronError, e: + logging.error('[%s] %s' % (item, e.value)) + + logging.info('Created %i xml files' % created_files) + + +def receive_file(directory, url, xml_file): + 'Generic download function' + + filename = os.path.join(directory, xml_file) + url.append(xml_file) + + try: + with closing(cStringIO.StringIO()) as data: + with closing(urllib.urlopen(''.join(url))) as resource: + data.write(resource.read()) + + with open(filename, 'w') as output: + output.write(data.getvalue()) + + except IOError: + logging.error('File %s - Download failed!' % filename) + + logging.debug('File %s - %sKB received' % + (filename, os.path.getsize(filename)/1024)) + + +def parse_nvd_dict(directory): + 'Returns a dictionary from the National Vulnerability Database' + + nvd = dict() + + for nvdfile in os.listdir(directory): + filename = os.path.join(directory, nvdfile) + try: + with open(filename, 'r+') as xml_data: + memory_map = mmap.mmap(xml_data.fileno(), 0) + + except SyntaxError: + continue + + root = et.parse(memory_map).getroot() + namespace = root.tag[:-3] + + for tree in root: + cve = { + 'cve' : tree.get('name'), + 'published' : tree.get('published'), + 'severity' : tree.get('severity'), + 'vector' : tree.get('CVSS_vector'), + 'score' : tree.get('CVSS_score') + } + + desc = tree.find('%sdesc/%sdescript/' % (namespace, namespace)) + if desc is not None: + cve['desc'] = desc.text + + reftree = tree.find(namespace + 'refs') + reftree.tag = reftree.tag.replace(namespace, '') + for elem in reftree.findall('.//*'): + elem.tag = elem.tag.replace(namespace, '') + + bugref = et.SubElement(reftree, 'ref') + bugref.set('source', 'GENTOO') + bugref.set('url', '%sshow_bug.cgi?id=%s' % (BZURL, cve['cve'])) + bugref.text = 'Gentoo %s' % cve['cve'] + + cve['refs'] = reftree + + nvd[cve['cve']] = cve + + return nvd + +def parse_bugzilla_dict(directory, bugid): + 'Returns a vulnerability class containing information about a bug' + + filename = os.path.join(directory, bugid) + + try: + with open(filename, 'r+') as xml_data: + memory_map = mmap.mmap(xml_data.fileno(), 0) + root = et.parse(memory_map).getroot()[0] + + except IOError: + return + + string = str() + + try: + string = root.find('short_desc').text + except AttributeError: + CronError('No Cve') + + try: + cvelist = list() + string = string.replace('CAN', 'CVE') + + if string in REGEX['m_nomatch'].findall(string): + cvelist = [NOCVE] + + for (year, split_cves) in REGEX['grp_all'].findall(string): + for cve in REGEX['grp_split'].findall(split_cves): + cvelist.append('CVE-%s-%s' % (year, cve)) + + vul = { + 'bugid' : bugid, + 'cvelist' : cvelist, + 'cves' : list(), + 'arch' : root.find('rep_platform').text.lower(), + 'reporter' : root.find('reporter').text.lower(), + 'reported' : root.find('creation_ts').text, + 'status' : root.find('bug_status').text.lower(), + } + + for item in vul['cvelist']: + if item != NOCVE: + if item not in CVES: + CVES[item] = vul.bugid + else: + raise CronError('Duplicate: ' + CVES[item]) + + except AttributeError: + pass + + try: + wb = root.find('status_whiteboard').text; + vul['affected'] = interval_from_whiteboard(wb) + + if vul['affected'] == None: + raise CronError('Invalid whiteboard: ' + wb) + + except AttributeError: + raise CronError('Empty whiteboard') + + return vul + + +def interval_from_whiteboard(whiteboard): + 'Returns a list of intervals within a whiteboard string' + + upper_inc = None + upper = None + lower_inc = None + lower = None + + affected = list() + + while len(whiteboard.strip()) > 0: + match = REGEX['wb_match'].match(whiteboard) + if not match: + return None + + name = match.group(1) + comp1 = match.group(2) + vers1 = match.group(3) + comp2 = match.group(4) + vers2 = match.group(5) + whiteboard = match.group(6) + + if comp1 == '=' or comp1 == '==': + lower_inc = True + upper_inc = True + lower = vers1 + upper = vers1 + + if not REGEX['wb_version'].match(vers1): + return None + else: + for (char, version) in ((comp1, vers1), (comp2, vers2)): + + if char == '<': + upper_inc = False + upper = version + elif char == '<=' or char == '=<': + upper_inc = True + upper = version + elif char == '>': + lower_inc = False + lower = version + elif char == '>=' or char == '=>': + lower_inc = True + lower = version + elif char: + return None + + if version and not REGEX['wb_version'].match(version): + return None + + interval = { + 'name' : name, + 'lower' : lower, + 'upper' : upper, + 'lower_inc' : lower_inc, + 'upper_inc' : upper_inc + } + + affected.append(interval) + + return affected + + +def write_cve_file(directory, vul): + 'Write a bug file containing all important information for kernel-check' + + filename = os.path.join(directory, vul['bugid'] + '.xml') + + root = et.Element('vulnerability') + bugroot = et.SubElement(root, 'bug') + + for element in BUGORDER: + if element == 'affected': + affectedroot = et.SubElement(bugroot, 'affected') + for item in vul['affected']: + intnode = et.Element('interval') + intnode.set('source', item['name']) + + affectedroot.append(intnode) + + for i in ('lower', 'upper'): + if item[i]: + node = et.SubElement(intnode, i) + node.text = item[i] + node.set('inclusive', + str(item[i + '_inc']).lower()) + else: + node = et.SubElement(bugroot, element) + node.text = vul[element] + + for cve in vul['cves']: + cveroot = et.SubElement(root, 'cve') + if cve == NOCVE: + node = et.SubElement(cveroot, 'cve') + node.text = NOCVE + node = et.SubElement(cveroot, 'desc') + node.text = NOCVEDESC + else: + for element in CVEORDER: + if element == 'refs': + cveroot.append(cve[element]) + else: + node = et.SubElement(cveroot, element) + node.text = cve[element] + + with open(filename, 'w') as xmlout: + __indent__(root) + doc = et.ElementTree(root) + doc.write(xmlout, encoding='utf-8') + + +def __indent__(node, level=0): + 'Indents xml layout for printing' + + i = '\n' + level * ' ' * 4 + if len(node): + if not node.text or not node.text.strip(): + node.text = i + ' ' * 4 + if not node.tail or not node.tail.strip(): + node.tail = i + for node in node: + __indent__(node, level + 1) + if not node.tail or not node.tail.strip(): + node.tail = i + else: + if level and (not node.tail or not node.tail.strip()): + node.tail = i + + +if __name__ == '__main__': + main(sys.argv[1:]) + diff --git a/tools/findcommit.sh b/tools/findcommit.sh new file mode 100755 index 0000000..770078b --- /dev/null +++ b/tools/findcommit.sh @@ -0,0 +1,62 @@ +#!/bin/sh +# kernel-check -- Kernel security information +# Copyright 2009-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +TEXT=".*$@.*" +GITPATH="./" + +KNOWNCOMMITS="" +LASTFIXEDBRANCH="" +WHITEBOARD="" + +GOOD=$'\e[32;01m' +BAD=$'\e[31;01m' +BRACKET=$'\e[34;01m' +NORMAL=$'\e[0m' + +GITPATH="--git-dir=$GITPATH.git --work-tree=$GITPATH" +BRANCHES="`git $GITPATH branch -a | grep linux` origin/master" +for B in $BRANCHES ; do + COMMITS="`git $GITPATH rev-list --pretty=oneline "$B" | + grep "$TEXT" | cut -d " " -f 1`" + for C in $COMMITS ; do + if [ "${KNOWNCOMMITS/$C/}" == "$KNOWNCOMMITS" ] ; then + TAG="`git $GITPATH describe --contains --all "$C"`" + DESC="`git $GITPATH --no-pager log -1 --pretty=short "$C"`" + DESC="`echo "$DESC" | tr -s "\n" `" + DESC="${TAG/tags\//\n${GOOD}label${NORMAL} }\n${DESC}" + DESC="${DESC/commit/${GOOD}commit${NORMAL}}" + DESC="${DESC/Author:/${GOOD}author${NORMAL}}" + DESC="${DESC/ /${GOOD}title${NORMAL} ${BRACKET}}${NORMAL}\n" + echo -e "$DESC" + + VERSION="${TAG/tags\/v/}" + VERSION="${VERSION/~*/}" + VERSION="${VERSION/^*/}" + + if [ "$B" != "origin/master" ] ; then + THISBRANCH="${B/remotes\/origin\/linux-/}" + THISBRANCH="${THISBRANCH/.y/}" + REVISION="${THISBRANCH/*./}" + MAJORMINOR="${THISBRANCH/.${REVISION}/}" + let REVISION=REVISION+1 + NEXTBRANCH="${MAJORMINOR}.${REVISION}" + fi + if [ -z "$LASTFIXEDBRANCH" ] ; then + WHITEBOARD="$WHITEBOARD [linux <${VERSION}]" + else + if [ "${LASTFIXEDBRANCH}" == "${VERSION/-rc*/}" ] ; then + WHITEBOARD="${WHITEBOARD} ${BAD}[linux >=" \ + "${LASTFIXEDBRANCH} <${VERSION}]${NORMAL}" + else + WHITEBOARD="${WHITEBOARD} [linux >=" \ + "${LASTFIXEDBRANCH} <${VERSION}]" + fi + fi + LASTFIXEDBRANCH=$NEXTBRANCH + KNOWNCOMMITS="$KNOWNCOMMITS $C" + fi + done +done +echo -e "${GOOD}Whiteboard${NORMAL}\n${WHITEBOARD:1}\n" diff --git a/tools/testsuite.py b/tools/testsuite.py new file mode 100755 index 0000000..1a9287c --- /dev/null +++ b/tools/testsuite.py @@ -0,0 +1,212 @@ +#!/usr/bin/env python + +import unittest +import sys +import kernellib as lib +import guidexml + +""" +import matplotlib.pyplot as pyplot + + +def draw_graph(): + 'Draws a graph x=kernel releases, y=amount of vulnerabilities' + +LINUX26_RELEASES = [ +'0', '1', '2', '3', '4', '5', '6', '7', '8', '8.1', '9', '10', '11', '11.1', +'11.2', '11.3', '11.4', '11.5', '11.6', '11.7', '11.8', '11.9', '11.10', +'11.11', '11.12', '12', '12.1', '12.2', '12.3', '12.4', '12.5', '12.6', +'13', '13.1', '13.2', '13.3', '13.4', '13.5', '14', '14.1', '14.2', '14.3', +'14.4', '14.5', '14.6', '14.7', '15', '15.1', '15.2', '15.3', '15.4', '15.5', +'15.6', '15.7', '16', '16.1', '16.2', '16.3', '16.4', '16.5', '16.6', '16.7', +'16.8', '16.9', '16.10', '16.11', '16.12', '16.13', '16.14', '16.15', '16.16', +'16.17', '16.18', '16.19', '16.20', '16.21', '16.22', '16.23', '16.24', +'16.25', '16.26', '16.27', '16.28', '16.29', '16.30', '16.31', '16.32', +'16.33', '16.34', '16.35', '16.36', '16.37', '16.38', '16.39', '16.40', +'16.41', '16.42', '16.43', '16.44', '16.45', '16.46', '16.47', '16.48', +'16.49', '16.50', '16.51', '16.52', '16.53', '16.54', '16.55', '16.56', +'16.57', '16.58', '16.59', '16.60', '16.61', '16.62', '17', '17.1', '17.2', +'17.3', '17.4', '17.5', '17.6', '17.7', '17.8', '17.9', '17.10', '17.11', +'17.12', '17.13', '17.14', '18', '18.1', '18.2', '18.3', '18.4', '18.5', +'18.6', '18.7', '18.8', '19', '19.1', '19.2', '19.3', '19.4', '19.5', '19.6', +'19.7', '20', '20.1', '20.2', '20.3', '20.4', '20.5', '20.6', '20.7', '20.8', +'20.9', '20.10', '20.11', '20.12', '20.13', '20.14', '20.15', '20.16', '20.17', +'20.18', '20.19', '20.20', '20.21', '21', '21.1', '21.2', '21.3', '21.4', +'21.5', '21.6', '21.7', '22', '22.1', '22.2', '22.3', '22.4', '22.5', '22.6', +'22.7', '22.8', '22.9', '22.10', '22.11', '22.12', '22.13', '22.14', '22.15', +'22.16', '22.17', '22.18', '22.19', '23', '23.1', '23.2', '23.3', '23.4', +'23.5', '23.6', '23.7', '23.8', '23.9', '23.10', '23.11', '23.12', '23.13', +'23.14', '23.15', '23.16', '23.17', '24', '24.1', '24.2', '24.3', '24.4', +'24.5', '24.6', '24.7', '25', '25.1', '25.2', '25.3', '25.4', '25.5', '25.6', +'25.7', '25.8', '25.9', '25.10', '25.11', '25.12', '25.13', '25.14', '25.15', +'25.16', '25.17', '25.18', '25.19', '25.20', '26', '26.1', '26.2', '26.3', +'26.4', '26.5', '26.6', '26.7', '26.8', '27', '27.1', '27.2', '27.3', '27.4', +'27.5', '27.6', '27.7', '27.8', '27.9', '27.10', '27.11', '27.12', '27.13', +'27.14', '27.15', '27.16', '27.17', '27.18', '27.19', '27.20', '27.21', +'27.22', '27.23', '27.24', '27.25', '27.26', '27.27', '27.28', '28', '28.1', +'28.2', '28.3', '28.4', '28.5', '28.6', '28.7', '28.8', '28.9', '28.10', '29', +'29.1', '29.2', '29.3', '29.4', '29.5', '29.6', '30', '30.1', '30.2', '30.3', +'30.4', '30.5' +] + +vul, line, value = [], [], [] + +for item in LINUX26_RELEASES: + kernel = lib.Kernel('gentoo-sources') + kernel.revision = '' + kernel.version = '2.6.' + item + best = lib.best_version(kernel.source) + schedule = lib.parse_cve_files('out', kernel, best, 'all') #FIXME + vul.append(len(schedule.canfix)) + if '.' not in item: + line.append(len(schedule.canfix)) + value.append(len(vul) - 1) + +pyplot.plot(vul, color='#7A5ADA', linewidth=1) +for i in range(0, len(line)): + pyplot.bar(value[i], line[i], color='#7A5ADA', edgecolor='#FFFFFF') + +pyplot.axis('tight') +pyplot.ylabel('Number of vulnerabilities') +pyplot.xlabel('Kernel release') +pyplot.show() + + +def write_guidexml(): + 'Testcases for guidexml' + +doc = guidexml.Document('mydocument', '2.0', 'Sehr nuetzliches infos', 'en', + '/doc/en/bla') + +doc.addAuthor('creator', 'asyme', 'asymmail@googlemail.de') +doc.addAuthor('creator', 'rbu') + +chap = guidexml.Chapter('1 chapter') +sect = guidexml.Section('1 section') + +taguri = guidexml.uri("http://google.de") +tagpara = guidexml.paragraph("hello world, Visit: %s.das ist ein sehr langer' \ + 'text mit mehr als MAXLENGTH Zeichen." % + repr(taguri)) + +doc.append(chap) +chap.append(sect) +sect.append(tagpara) + +doc.create('/', 'file') + + +def test_kernel_version(): + 'Test if kernel releases are parsed correctly' + + kernelcases = { + '2.6.29.1' : + {'source' : 'vanilla', + 'revision' : 'r0', + 'version' : '2.6.29.1'}, + '2.6.18-xen-r11' : + {'source' : 'xen', + 'revision' : 'r11', + 'version' : '2.6.18'}, + '2.6.27-gentoo-r2' : + {'source' : 'gentoo', + 'revision' : 'r2', + 'version' : '2.6.27'}, + '2.6.28-hardened-r77' : + {'source' : 'hardened', + 'revision' : 'r77', + 'version' : '2.6.28'}, + '2.6.28-r7' : + {'source' : 'vanilla', + 'revision' : 'r7', + 'version' : '2.6.28'}, + '2.6.28-rc8' : + {'source' : 'vanilla', + 'revision' : 'r0', + 'version' : '2.6.28_rc8'}, + '2.6.28-rc8-git6' : + {'source' : 'git', + 'revision' : 'r6', + 'version' : '2.6.28_rc8'}, + '2' : + {'source' : 'vanilla', + 'revision' : 'r0', + 'version' : '2'}, + '2.6.28-hardened-r7777' : + {'source' : 'hardened', + 'revision' : 'r0', + 'version' : '2.6.28'}, + '2.6.2833-hardened-r7' : + None, + +} + + suite = unittest.TestSuite() + + for name, dict in kernelcases.iteritems(): + newtest = KernelVersionTestCase(name, dict) + suite.addTest(newtest) + + unittest.TextTestRunner(verbosity=2).run(suite) + + +class KernelVersionTestCase(unittest.TestCase): + + def __init__(self, name, dict): + unittest.TestCase.__init__(self, 'testFunction') + self.name = name + self.dict = dict + + def testFunction(self): + rvalue = lib.extract_version_from(self.name) + self.assertEqual(self.dict, rvalue) +""" + + +def test_interval(): + 'Test if a kernel release is affected' + + kernelcase = ['gentoo', '2.6.30', 'r4', '2.6.30-5'] + intervalcases = { + '[linux >=2.6.27 <=2.6.30] [gp <2.6.30.3]' : False, + '[linux >=2.6.27 <=2.6.30] [gp <2.6.30.6]' : True, + '[linux >=2.6.28 <=2.6.31] [gp <=2.6.30.5]' : True, + '[linux >=2.6.26 <2.6.28] [linux >2.6.29 <=2.6.30]' : True, + + } + + suite = unittest.TestSuite() + + kernel = lib.Kernel(kernelcase[0]) + kernel.version = kernelcase[1] + kernel.revision = kernelcase[2] + kernel_gp = lib.Genpatch(kernelcase[3]) + + for wb, affected in intervalcases.iteritems(): + interval_list = lib.interval_from_whiteboard(wb) + + newtest = IntervalTestCase(interval_list, kernel, kernel_gp, affected) + suite.addTest(newtest) + + unittest.TextTestRunner(verbosity=2).run(suite) + + +class IntervalTestCase(unittest.TestCase): + + def __init__(self, interval_list, kernel, kernel_gp, affected): + unittest.TestCase.__init__(self, 'testFunction') + self.interval_list = interval_list + self.kernel = kernel + self.kernel_gp = kernel_gp + self.item = lib.Vulnerability('000000') + self.affected = affected + + def testFunction(self): + rvalue = lib.is_affected(self.interval_list, self.kernel, + self.kernel_gp, self.item) + self.assertEqual(self.affected, rvalue) + + +if __name__ == '__main__': + test_interval() + |