1# Copyright (C) 2014 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#   http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15from __future__ import print_function
16import collections
17import sys
18
19class Logger(object):
20
21  class Level(object):
22    NoOutput, Error, Info = range(3)
23
24  class Color(object):
25    Default, Blue, Gray, Purple, Red, Green = range(6)
26
27    @staticmethod
28    def terminalCode(color, out=sys.stdout):
29      if not out.isatty():
30        return ''
31      elif color == Logger.Color.Blue:
32        return '\033[94m'
33      elif color == Logger.Color.Gray:
34        return '\033[37m'
35      elif color == Logger.Color.Purple:
36        return '\033[95m'
37      elif color == Logger.Color.Red:
38        return '\033[91m'
39      elif color == Logger.Color.Green:
40        return '\033[32m'
41      else:
42        return '\033[0m'
43
44  Verbosity = Level.Info
45
46  @staticmethod
47  def log(text, level=Level.Info, color=Color.Default, newLine=True, out=sys.stdout):
48    if level <= Logger.Verbosity:
49      text = Logger.Color.terminalCode(color, out) + text + \
50             Logger.Color.terminalCode(Logger.Color.Default, out)
51      if newLine:
52        print(text, file=out)
53      else:
54        print(text, end="", file=out)
55      out.flush()
56
57  @staticmethod
58  def fail(msg, file=None, line=-1, lineText=None, variables=None):
59    Logger.log("error: ", Logger.Level.Error, color=Logger.Color.Red, newLine=False, out=sys.stderr)
60    Logger.log(msg, Logger.Level.Error, out=sys.stderr)
61
62    if lineText:
63      loc = ""
64      if file:
65        loc += file + ":"
66      if line > 0:
67        loc += str(line) + ":"
68      if loc:
69        loc += " "
70      Logger.log(loc, Logger.Level.Error, color=Logger.Color.Gray, newLine=False, out=sys.stderr)
71      Logger.log(lineText, Logger.Level.Error, out=sys.stderr)
72
73    if variables:
74      longestName = 0
75      for var in variables:
76        longestName = max(longestName, len(var))
77
78      for var in collections.OrderedDict(sorted(variables.items())):
79        padding = ' ' * (longestName - len(var))
80        Logger.log(var, Logger.Level.Error, color=Logger.Color.Green, newLine=False, out=sys.stderr)
81        Logger.log(padding, Logger.Level.Error, newLine=False, out=sys.stderr)
82        Logger.log(" = ", Logger.Level.Error, newLine=False, out=sys.stderr)
83        Logger.log(variables[var], Logger.Level.Error, out=sys.stderr)
84
85    sys.exit(1)
86
87  @staticmethod
88  def startTest(name):
89    Logger.log("TEST ", color=Logger.Color.Purple, newLine=False)
90    Logger.log(name + "... ", newLine=False)
91
92  @staticmethod
93  def testPassed():
94    Logger.log("PASS", color=Logger.Color.Blue)
95
96  @staticmethod
97  def testFailed(msg, assertion, variables):
98    Logger.log("FAIL", color=Logger.Color.Red)
99    Logger.fail(msg, assertion.fileName, assertion.lineNo, assertion.originalText, variables)
100