⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 boostbuild.py

📁 C++的一个好库。。。现在很流行
💻 PY
📖 第 1 页 / 共 2 页
字号:
            print self.stdout()
            print "Expected STDERR =========="
            print stderr
            print "Actual STDERR ============"
            print actual_stderr
            self.maybe_do_diff(actual_stderr, stderr)
            self.fail_test(1, dump_stdio = 0)

        self.tree = build_tree(self.workdir)
        self.difference = trees_difference(self.previous_tree, self.tree)
        self.difference.ignore_directories()
        self.unexpected_difference = copy.deepcopy(self.difference)

        self.last_build_time = time.time()

    def read(self, name):
        return open(self.native_file_name(name), "rb").read()

    def read_and_strip(self, name):
        lines = open(self.native_file_name(name), "rb").readlines()
        result = string.join(map(string.rstrip, lines), "\n")
        if lines and lines[-1][-1] == '\n':
            return result + '\n'
        else:
            return result
    
    def fail_test(self, condition, dump_stdio = 1, *args):
        # If test failed, print the difference        
        if condition and hasattr(self, 'difference'):            
            print '-------- all changes caused by last build command ----------'
            self.difference.pprint()
            
        if condition and dump_stdio:
            self.dump_stdio()

        if '--preserve' in sys.argv:
            print 
            print "*** Copying the state of working dir into 'failed_test' ***"
            print 
            path = os.path.join(self.original_workdir, "failed_test")
            if os.path.isdir(path):
                shutil.rmtree(path, ignore_errors=0)
            elif os.path.exists(path):
                raise "The path " + path + " already exists and is not directory";
            shutil.copytree(self.workdir, path)
                        
        TestCmd.TestCmd.fail_test(self, condition, *args)
        
    # A number of methods below check expectations with actual difference
    # between directory trees before and after build.
    # All the 'expect*' methods require exact names to be passed.
    # All the 'ignore*' methods allow wildcards.

    # All names can be lists, which are taken to be directory components
    def expect_addition(self, names):        
        for name in self.adjust_names(names):
                try:
                        self.unexpected_difference.added_files.remove(name)
                except:
                        print "File %s not added as expected" % (name,)
                        self.fail_test(1)

    def ignore_addition(self, wildcard):
        self.ignore_elements(self.unexpected_difference.added_files, wildcard)

    def expect_removal(self, names):
        for name in self.adjust_names(names):
                try:
                        self.unexpected_difference.removed_files.remove(name)
                except:
                        print "File %s not removed as expected" % (name,)
                        self.fail_test(1)

    def ignore_removal(self, wildcard):
        self.ignore_elements(self.unexpected_difference.removed_files, wildcard)

    def expect_modification(self, names):
        for name in self.adjust_names(names):
                try:
                        self.unexpected_difference.modified_files.remove(name)
                except:
                        print "File %s not modified as expected" % (name,)
                        self.fail_test(1)

    def ignore_modification(self, wildcard):
        self.ignore_elements(self.unexpected_difference.modified_files, wildcard)

    def expect_touch(self, names):
        
        d = self.unexpected_difference
        for name in self.adjust_names(names):

            # We need to check in both touched and modified files.
            # The reason is that:
            # (1) for windows binaries often have slight
            # differences even with identical inputs
            # (2) Intel's compiler for Linux has the same behaviour        
            filesets = [d.modified_files, d.touched_files]

            while filesets:
                try:
                    filesets[-1].remove(name)
                    break
                except ValueError:
                    filesets.pop()

            if not filesets:
                print "File %s not touched as expected" % (name,)
                self.fail_test(1)


    def ignore_touch(self, wildcard):
        self.ignore_elements(self.unexpected_difference.touched_files, wildcard)

    def ignore(self, wildcard):
        self.ignore_elements(self.unexpected_difference.added_files, wildcard)
        self.ignore_elements(self.unexpected_difference.removed_files, wildcard)
        self.ignore_elements(self.unexpected_difference.modified_files, wildcard)
        self.ignore_elements(self.unexpected_difference.touched_files, wildcard)

    def expect_nothing(self, names):
        for name in self.adjust_names(names):
            if name in self.difference.added_files:
                print "File %s is added, but no action was expected" % (name,)
                self.fail_test(1)
            if name in self.difference.removed_files:
                print "File %s is removed, but no action was expected" % (name,)
                self.fail_test(1)
                pass
            if name in self.difference.modified_files:
                print "File %s is modified, but no action was expected" % (name,)
                self.fail_test(1)
            if name in self.difference.touched_files:
                print "File %s is touched, but no action was expected" % (name,)
                self.fail_test(1)

    def expect_nothing_more(self):

        # not totally sure about this change, but I don't see a good alternative
        if windows:
            self.ignore('*.ilk') # msvc incremental linking files
            self.ignore('*.pdb') # msvc program database files
            self.ignore('*.rsp') # response files
            self.ignore('*.tds') # borland debug symbols

        # debug builds of bjam built with gcc produce this profiling data
        self.ignore('gmon.out')
        self.ignore('*/gmon.out')
            
        if not self.unexpected_difference.empty():
           print 'FAILED'
           print '------- The following changes were unexpected ------- '
           self.unexpected_difference.pprint()
           self.fail_test(1)       

    def expect_content(self, name, content, exact=0):
        name = self.adjust_names(name)[0]
        try:
            if exact:
                actual = self.read(name)
            else:
                actual = string.replace(self.read_and_strip(name), "\\", "/")
        except IOError:
            print "Note: could not open file", name
            self.fail_test(1)

        content = string.replace(content, "$toolset", self.toolset)

        if actual != content:
            print "Expected:\n"
            print content
            print "Got:\n"
            print actual
            self.fail_test(1)

    def maybe_do_diff(self, actual, expected):
        if os.environ.has_key("DO_DIFF") and os.environ["DO_DIFF"] != '':
            
            e = tempfile.mktemp("expected")
            a = tempfile.mktemp("actual")
            open(e, "w").write(expected)
            open(a, "w").write(actual)
            print "DIFFERENCE"
            if os.system("diff -u " + e + " " + a):
                print "Unable to compute difference"               
            os.unlink(e)
            os.unlink(a)    
        else:
            print "Set environmental variable 'DO_DIFF' to examine difference." 

    # Helpers
    def mul(self, *arguments):
        if len(arguments) == 0:
                return None
        else:
                here = arguments[0]
                if type(here) == type(''):
                        here = [here]

                if len(arguments) > 1:
                        there = apply(self.mul, arguments[1:])
                        result = []
                        for i in here:
                                for j in there:
                                        result.append(i + j)
                        return result
                else:
                        return here



    # Internal methods
    def ignore_elements(self, list, wildcard):
        """Removes in-place, element of 'list' that match the given wildcard."""
        list[:] = filter(lambda x, w=wildcard: not fnmatch.fnmatch(x, w), list)

    def adjust_lib_name(self, name):
        global lib_prefix
        result = name
        
        pos = string.rfind(name, ".")
        if pos != -1:
            suffix = name[pos:]
            if suffix in [".lib", ".dll"]:
                (head, tail) = os.path.split(name)
                if lib_prefix:
                    tail = "lib" + tail
                    result = os.path.join(head, tail)
        return result
                
    def adjust_suffix(self, name):
        if not self.translate_suffixes:
            return name
        
        pos = string.rfind(name, ".")
        if pos != -1:
            suffix = name[pos:]
            name = name[:pos]

            if suffixes.has_key(suffix):
                suffix = suffixes[suffix]
        else:
            suffix = ''

        return name + suffix

    # Acceps either string of list of string and returns list of strings
    # Adjusts suffixes on all names.
    def adjust_names(self, names):
        if type(names) == types.StringType:
                names = [names]
        r = map(self.adjust_lib_name, names)
        r = map(self.adjust_suffix, r)
        r = map(lambda x, t=self.toolset: string.replace(x, "$toolset", t), r)
        return r

    def native_file_name(self, name):
        name = self.adjust_names(name)[0]
        elements = string.split(name, "/")
        return os.path.normpath(apply(os.path.join, [self.workdir]+elements))

    # Wait while time is no longer equal to the time last "run_build_system"
    # call finished.
    def wait_for_time_change(self):
        while int(time.time()) < int(self.last_build_time) + 1:
            time.sleep(0.1)

            
class List:

    def __init__(self, s=""):
        elements = []
        if isinstance(s, type("")):          
            # Have to handle espaced spaces correctly
            s = string.replace(s, "\ ", '\001')
            elements = string.split(s)
        else:
            elements = s;
            
        self.l = []            
        for e in elements:
            self.l.append(string.replace(e, '\001', ' '))

    def __len__(self):
        return len(self.l)

    def __getitem__(self, key):
        return self.l[key]

    def __setitem__(self, key, value):
        self.l[key] = value

    def __delitem__(self, key):
        del self.l[key]

    def __str__(self):
        return str(self.l)

    def __repr__(self):
        return ( self.__module__ + '.List('
                 + repr(string.join(self.l, ' '))
                 + ')')

    def __mul__(self, other):        
        result = List()
        if not isinstance(other, List):
            other = List(other)
        for f in self:
            for s in other:
                result.l.append(f + s)
        return result

    def __rmul__(self, other):
        if not isinstance(other, List):
            other = List(other)        
        return List.__mul__(other, self)

    def __add__(self, other):
        result = List()
        result.l = self.l[:] + other.l[:]
        return result

# quickie tests. Should use doctest instead.
if __name__ == '__main__':
    assert str(List("foo bar") * "/baz") == "['foo/baz', 'bar/baz']"
    assert repr("foo/" * List("bar baz")) == "__main__.List('foo/bar foo/baz')"
    print 'tests passed'




⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -