1# coding=utf-8 2# Copyright (c) 2014, 2016, 2019 Intel Corporation 3 4# Permission is hereby granted, free of charge, to any person obtaining a copy 5# of this software and associated documentation files (the "Software"), to deal 6# in the Software without restriction, including without limitation the rights 7# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8# copies of the Software, and to permit persons to whom the Software is 9# furnished to do so, subject to the following conditions: 10 11# The above copyright notice and this permission notice shall be included in 12# all copies or substantial portions of the Software. 13 14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20# SOFTWARE. 21 22"""Tests for log.py module.""" 23 24import collections 25import io 26import sys 27import threading 28 29import pytest 30 31import framework.log as log 32 33# pylint: disable=no-self-use,protected-access 34 35 36@pytest.fixture 37def log_state(): 38 """Create a unique state instance per test.""" 39 return {'total': 1, 'complete': 0, 'lastlength': 0, 'running': [], 40 'summary': collections.defaultdict(lambda: 0)} 41 42 43class TestLogFactory(object): 44 """Tests for the LogFactory class.""" 45 46 class TestGet(object): 47 """Tests for the LogFactory.get method.""" 48 49 def test_returns_log(self): 50 """Returns a BaseLog derived instance.""" 51 logger = log.LogManager('quiet', 100) 52 log_inst = logger.get() 53 assert isinstance(log_inst, log.BaseLog) 54 55 def test_log_state_update(self): 56 """log.BaseLog.log updates shared state managed by LogManager""" 57 logger = log.LogManager('quiet', 100) 58 log_inst = logger.get() 59 log_inst.start(None) 60 log_inst.log('pass') 61 62 assert logger._state['total'] == 100 63 assert logger._state['summary'] == {'pass': 1} 64 assert logger._state['complete'] == 1 65 66 67class TestQuietLog(object): 68 """Test QuietLog class.""" 69 70 class TestOutput(object): 71 """Test the output of the various methods.""" 72 73 @pytest.fixture(autouse=True, scope='function') 74 def mock_stdout(self, mocker): 75 mocker.patch.object(sys, 'stdout', io.StringIO()) 76 77 def test_log(self, log_state): # pylint: disable=redefined-outer-name 78 """Test the output of the log method.""" 79 quiet = log.QuietLog(log_state, threading.Lock()) 80 quiet.start(None) 81 quiet.log('pass') 82 sys.stdout.seek(0) 83 84 actual = sys.stdout.read() 85 assert actual == b'[1/1] pass: 1 -\n' 86 87 def test_summary(self, log_state): # pylint: disable=redefined-outer-name 88 """Test the output of the summary method.""" 89 quiet = log.QuietLog(log_state, threading.Lock()) 90 # Call log to set the total correctly, then truncate and remove the 91 # values, so the we can test 92 quiet.start(None) 93 quiet.log('pass') 94 sys.stdout.seek(0) 95 sys.stdout.truncate() 96 97 quiet.summary() 98 sys.stdout.seek(0) 99 100 # Because of the 'lastlength' mechanims there will likely be 101 # trainling whitespace after the the output, it's not useful to 102 # test that here, so just strip it. 103 assert sys.stdout.read().rstrip() == b'[1/1] pass: 1' 104 105 def test_start(self, log_state): # pylint: disable=redefined-outer-name 106 """Test that the start method doesn't have output.""" 107 quiet = log.QuietLog(log_state, threading.Lock()) 108 quiet.start(None) 109 quiet.start('foo') 110 sys.stdout.seek(0) 111 112 actual = sys.stdout.read() 113 assert actual == b'' 114 115 116class TestVerboseLog(object): 117 """Tests for the VerboseLog class.""" 118 119 class TestOutput(object): 120 """Test the output of the various methods.""" 121 122 @pytest.fixture(autouse=True, scope='function') 123 def mock_stdout(self, mocker): 124 mocker.patch.object(sys, 'stdout', io.StringIO()) 125 126 def test_log(self, log_state): # pylint: disable=redefined-outer-name 127 """Test the output of the log method.""" 128 l = log.VerboseLog(log_state, threading.Lock()) 129 l.start('foo') 130 sys.stdout.seek(0) 131 sys.stdout.truncate() 132 133 l.log('pass') 134 sys.stdout.seek(0) 135 136 actual = sys.stdout.read() 137 assert actual == b'pass: foo\n\n[1/1] pass: 1 /\n' 138 139 def test_summary(self, log_state): # pylint: disable=redefined-outer-name 140 """Test the output of the summary method.""" 141 l = log.VerboseLog(log_state, threading.Lock()) 142 l.start('foo') 143 l.log('pass') 144 sys.stdout.seek(0) 145 sys.stdout.truncate() 146 147 l.summary() 148 sys.stdout.seek(0) 149 150 assert sys.stdout.read().rstrip() == b'[1/1] pass: 1' 151 152 def test_start(self, log_state): # pylint: disable=redefined-outer-name 153 """Test that the start method doesn't have output.""" 154 l = log.VerboseLog(log_state, threading.Lock()) 155 l.start('foo') 156 sys.stdout.seek(0) 157 158 assert sys.stdout.read().rstrip() == b'running: foo\n\n[0/1] \\' 159 160 161class TestDummyLog(object): 162 """Tests for the DummyLog class.""" 163 164 class TestOutput(object): 165 """Test the output of the various methods.""" 166 167 @pytest.fixture(autouse=True, scope='function') 168 def mock_stdout(self, mocker): 169 mocker.patch.object(sys, 'stdout', io.StringIO()) 170 171 def test_log(self, log_state): # pylint: disable=redefined-outer-name 172 """Test the output of the log method.""" 173 quiet = log.DummyLog(log_state, threading.Lock()) 174 quiet.start(None) 175 quiet.log('pass') 176 sys.stdout.seek(0) 177 178 actual = sys.stdout.read() 179 assert actual == b'' 180 181 def test_summary(self, log_state): # pylint: disable=redefined-outer-name 182 """Test the output of the summary method.""" 183 quiet = log.DummyLog(log_state, threading.Lock()) 184 quiet.summary() 185 sys.stdout.seek(0) 186 187 actual = sys.stdout.read() 188 assert actual == b'' 189 190 def test_start(self, log_state): # pylint: disable=redefined-outer-name 191 """Test that the start method doesn't have output.""" 192 quiet = log.DummyLog(log_state, threading.Lock()) 193 quiet.start('foo') 194 sys.stdout.seek(0) 195 196 actual = sys.stdout.read() 197 assert actual == b'' 198