blob: 9d14947ece5c1de3d6c207e47d32b290caa746da [file] [log] [blame]
# Copyright (c) 2018 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
import os
import re
import time
from autotest_lib.client.bin import test
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import chrome
from autotest_lib.client.cros import cros_logging
class MemoryKillsMonitor:
"""A util class for reading kill events."""
_LOG_FILE = '/var/log/chrome/chrome'
_PATTERN_DISCARD = re.compile(
'tab_manager_delegate_chromeos.*:(\d+) Killed tab')
_PATTERN_OOM = re.compile('Tab OOM-Killed Memory details:')
def __init__(self):
self._log_reader = cros_logging.ContinuousLogReader(self._LOG_FILE)
def check_event(self):
"""Returns the first monitored kill event or empty string"""
for line in self._log_reader.read_all_logs():
matched = self._PATTERN_DISCARD.search(line)
if matched:
logging.info('Matched line %s', line)
return 'LOW_MEMORY_KILL_TAB'
matched = self._PATTERN_OOM.search(line)
if matched:
logging.info('Matched line %s', line)
return 'OOM_KILL'
return ''
class platform_LowMemoryTest(test.test):
"""Memory pressure test."""
version = 1
def create_alloc_page(self, cr, size_mb):
"""The program in alloc.html allocates a large array with random data.
"""
url = cr.browser.platform.http_server.UrlOf(
os.path.join(self.bindir, 'alloc.html'))
url += '?alloc=' + str(size_mb)
tab = cr.browser.tabs.New()
tab.Navigate(url)
tab.WaitForDocumentReadyStateToBeComplete()
tab.WaitForJavaScriptCondition(
"document.hasOwnProperty('out') == true", timeout=60)
def run_once(self):
"""Runs the test once."""
# 1 for initial tab opened
n_tabs = 1
kills_monitor = MemoryKillsMonitor()
last_event = ''
# Open tabs until a tab discard notification or OOM arrives.
with chrome.Chrome(init_network_controller=True) as cr:
cr.browser.platform.SetHTTPServerDirectories(self.bindir)
while last_event == '':
self.create_alloc_page(cr, 800)
time.sleep(3)
n_tabs += 1
last_event = kills_monitor.check_event()
# Test is successful if at least one Chrome tab is killed by tab
# discarder before kernel OOM killer invoked.
if last_event == 'OOM_KILL':
raise error.TestFail('OOM Kill happends before a tab is killed')
result_title = 'NumberOfTabsAtFirstDiscard'
self.write_perf_keyval({result_title : n_tabs})
self.output_perf_value(description=result_title, value=n_tabs,
higher_is_better=True)