<commit_before># -*- coding: utf-8 -*-

# Copyright 2013 <NAME>
# <EMAIL>

# This file is part of ActionTree. http://jacquev6.github.com/ActionTree

# ActionTree is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License
# as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

# ActionTree is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.

# You should have received a copy of the GNU Lesser General Public License along with ActionTree.  If not, see <http://www.gnu.org/licenses/>.

import unittest
import cairo
import MockMockMock
import io
import os
import hashlib
import traceback

import ActionTree
from ActionTree.Drawings import ExecutionReport


class Report(unittest.TestCase):
    def setUp(self):
        unittest.TestCase.setUp(self)
        self.actionMocks = MockMockMock.Engine()
        self.actionMocks.unordered  # @todo in MockMockMock, find a better syntax to use grouping without "with" keyword

    def tearDown(self):
        self.actionMocks.tearDown()
        unittest.TestCase.tearDown(self)

    # Expect several digests because cairo may not produce exactly the same file on
    # all platorms and versions
    def __checkDrawing(self, a, width, expectedDigests):
        testName = None
        for (_, _, functionName, _) in traceback.extract_stack():
            if functionName.startswith("test"):
                testName = "Report." + functionName
                break
        self.assertIsNot(testName, None)

        r = ExecutionReport(a)
        height = r.getHeight(cairo.Context(cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1)))

        image = cairo.ImageSurface(cairo.FORMAT_RGB24, width, height)
        ctx = cairo.Context(image)
        ctx.set_source_rgb(1, 1, 1)
        ctx.paint()
        ctx.set_source_rgb(0, 0, 0)
        r.draw(ctx, width)
        f = io.BytesIO()
        image.write_to_png(f)
        digest = hashlib.md5(f.getvalue()).hexdigest()
        fileName = os.path.join("ActionTree", "tests", "drawings", testName + "." + digest + ".png")
        with open(fileName, "wb") as png:
            png.write(f.getvalue())
        if digest not in expectedDigests.values():
            self.assertTrue(False, "Check file " + fileName + ". If it is OK, modify test " + testName + " to accept digest " + digest)
        f.close()

    def __createMockedAction(self, name, label, dependencies, beginTime, endTime, status):
        a = self.actionMocks.create(name)
        a.expect.label.andReturn(label)
        a.expect.beginTime.andReturn(beginTime)
        a.expect.endTime.andReturn(endTime)
        a.expect.status.andReturn(status)
        a.expect.getDependencies().andReturn(dependencies)
        return a.object

    def testComplexLabel(self):
        a = self.__createMockedAction("a", ("a", "complex", [42, "label"]), [], 10.5, 13.5, ActionTree.Action.Successful)

        self.__checkDrawing(a, 400, {"Python 2.7, Cygwin": "5f3cfe117ab21440c9d7bc0f8d1c9e70"})

    def testOneSuccessfulAction(self):
        a = self.__createMockedAction("a", "label", [], 10.5, 13.5, ActionTree.Action.Successful)

        self.__checkDrawing(a, 200, {"Python 2.7, Cygwin": "80da16a2a8c0b5a3cfe71566c1d1a750"})

    def testOneFailedAction(self):
        a = self.__createMockedAction("a", "label", [], 10.5, 13.5, ActionTree.Action.Failed)

        self.__checkDrawing(a, 200, {"Python 2.7, Cygwin": "62ad8ef401b9bc37104e58a597e04d13"})

    def testOneCanceledAction(self):
        a = self.__createMockedAction("a", "label", [], 10.5, 13.5, ActionTree.Action.Canceled)

        self.__checkDrawing(a, 200, {"Python 2.7, Cygwin": "081c688ac8678ec4ea5f1621c4e8044a"})

    def testTwoChainedActions(self):
        a1 = self.__createMockedAction("a1", "a1", [], 10.5, 13.5, ActionTree.Action.Successful)
        a2 = self.__createMockedAction("a2", "a2", [a1], 14.0, 15.5, ActionTree.Action.Successful)

        self.__checkDrawing(a2, 200, {"Python 2.7, Cygwin": "7ed1b75b6c45b594e643bf0128158d83"})

    def testActionWithTwoDependencies(self):
        a1 = self.__createMockedAction("a1", "a1", [], 10.5, 13.5, ActionTree.Action.Successful)
        a2 = self.__createMockedAction("a2", "a2", [], 11.5, 14.0, ActionTree.Action.Successful)
        a3 = self.__createMockedAction("a3", "a3", [a1, a2], 14.0, 15.5, ActionTree.Action.Successful)

        self.__checkDrawing(a3, 200, {"Python 2.7, Cygwin - 1": "e0ee94d2b3e57b05f13d8b0f459c0a2c", "Python 2.7, Cygwin - 2": "95202885fae962f9e652783e111276bb"})

    def testActionWithTwoDependents(self):
        a1 = self.__createMockedAction("a1", "a1", [], 12.5, 13.5, ActionTree.Action.Successful)
        a2 = self.__createMockedAction("a2", "a2", [a1], 15.0, 16.5, ActionTree.Action.Successful)
        a3 = self.__createMockedAction("a3", "a3", [a1], 14.0, 15.5, ActionTree.Action.Successful)
        a4 = self.__createMockedAction("a4", "a4", [a2, a3], 17.0, 17.5, ActionTree.Action.Successful)

        self.__checkDrawing(a4, 200, {"Python 2.7, Cygwin - 1": "4c4362ef3df4b0f631f03afd03ef45e0", "Python 2.7, Cygwin - 2": "240a21cfd5fdd8c22db4640938cb3e8d"})
<commit_msg>Make acceptation of new drawings easier<commit_after># -*- coding: utf-8 -*-

# Copyright 2013 <NAME>
# <EMAIL>

# This file is part of ActionTree. http://jacquev6.github.com/ActionTree

# ActionTree is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License
# as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

# ActionTree is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.

# You should have received a copy of the GNU Lesser General Public License along with ActionTree.  If not, see <http://www.gnu.org/licenses/>.

import unittest
import cairo
import MockMockMock
import io
import os
import hashlib
import traceback

import ActionTree
from ActionTree.Drawings import ExecutionReport


class Report(unittest.TestCase):
    def setUp(self):
        unittest.TestCase.setUp(self)
        self.actionMocks = MockMockMock.Engine()
        self.actionMocks.unordered  # @todo in MockMockMock, find a better syntax to use grouping without "with" keyword

    def tearDown(self):
        self.actionMocks.tearDown()
        unittest.TestCase.tearDown(self)

    # Expect several digests because cairo may not produce exactly the same file on
    # all platorms and versions
    def __checkDrawing(self, a, width):
        testName = None
        for (_, _, functionName, _) in traceback.extract_stack():
            if functionName.startswith("test"):
                testName = "Report." + functionName
                break
        self.assertIsNot(testName, None)

        r = ExecutionReport(a)
        height = r.getHeight(cairo.Context(cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1)))

        image = cairo.ImageSurface(cairo.FORMAT_RGB24, width, height)
        ctx = cairo.Context(image)
        ctx.set_source_rgb(1, 1, 1)
        ctx.paint()
        ctx.set_source_rgb(0, 0, 0)
        r.draw(ctx, width)
        f = io.BytesIO()
        image.write_to_png(f)
        digest = hashlib.md5(f.getvalue()).hexdigest()
        fileName = os.path.join("ActionTree", "tests", "drawings", testName + "." + digest + ".png")
        if not os.path.exists(fileName):
            with open(fileName, "wb") as png:
                png.write(f.getvalue())
            self.assertTrue(False, "Check file " + fileName + ".")
        f.close()

    def __createMockedAction(self, name, label, dependencies, beginTime, endTime, status):
        a = self.actionMocks.create(name)
        a.expect.label.andReturn(label)
        a.expect.beginTime.andReturn(beginTime)
        a.expect.endTime.andReturn(endTime)
        a.expect.status.andReturn(status)
        a.expect.getDependencies().andReturn(dependencies)
        return a.object

    def testComplexLabel(self):
        a = self.__createMockedAction("a", ("a", "complex", [42, "label"]), [], 10.5, 13.5, ActionTree.Action.Successful)

        self.__checkDrawing(a, 400)

    def testOneSuccessfulAction(self):
        a = self.__createMockedAction("a", "label", [], 10.5, 13.5, ActionTree.Action.Successful)

        self.__checkDrawing(a, 200)

    def testOneFailedAction(self):
        a = self.__createMockedAction("a", "label", [], 10.5, 13.5, ActionTree.Action.Failed)

        self.__checkDrawing(a, 200)

    def testOneCanceledAction(self):
        a = self.__createMockedAction("a", "label", [], 10.5, 13.5, ActionTree.Action.Canceled)

        self.__checkDrawing(a, 200)

    def testTwoChainedActions(self):
        a1 = self.__createMockedAction("a1", "a1", [], 10.5, 13.5, ActionTree.Action.Successful)
        a2 = self.__createMockedAction("a2", "a2", [a1], 14.0, 15.5, ActionTree.Action.Successful)

        self.__checkDrawing(a2, 200)

    def testActionWithTwoDependencies(self):
        a1 = self.__createMockedAction("a1", "a1", [], 10.5, 13.5, ActionTree.Action.Successful)
        a2 = self.__createMockedAction("a2", "a2", [], 11.5, 14.0, ActionTree.Action.Successful)
        a3 = self.__createMockedAction("a3", "a3", [a1, a2], 14.0, 15.5, ActionTree.Action.Successful)

        self.__checkDrawing(a3, 200)

    def testActionWithTwoDependents(self):
        a1 = self.__createMockedAction("a1", "a1", [], 12.5, 13.5, ActionTree.Action.Successful)
        a2 = self.__createMockedAction("a2", "a2", [a1], 15.0, 16.5, ActionTree.Action.Successful)
        a3 = self.__createMockedAction("a3", "a3", [a1], 14.0, 15.5, ActionTree.Action.Successful)
        a4 = self.__createMockedAction("a4", "a4", [a2, a3], 17.0, 17.5, ActionTree.Action.Successful)

        self.__checkDrawing(a4, 200)

{'fraction_non_alphanumeric': 0.12235067437379576, 'fraction_numerical': 0.04980732177263969, 'mean_word_length': 3.001927525057826, 'pattern_counts': {'":': 9, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6169527', 'n_tokens_mistral': 3713, 'n_tokens_neox': 3289, 'n_words': 805}