blob: ec824e775847b0b9ef93b9a15128fd8a665976b7 [file] [log] [blame]
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2018 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import atexit
import lldb
import lldb_webkit
import os
import sys
import unittest
from webkitpy.common.system.systemhost import SystemHost
# Run just the tests in this file with ./Tools/Scripts/test-webkitpy lldb_webkit_unittest
# We cache the lldb debug session state so that we don't create it again for each call to a serial_test_ method.
# We store it in a global variable so that we can delete this cached state on exit(3).
# FIXME: Remove this once test-webkitpy supports class and module fixtures (i.e. setUpClass()/setUpModule()
# are called exactly once per class/module).
cached_debug_session = None
# FIXME: Remove this once test-webkitpy supports class and module fixtures (i.e. setUpClass()/setUpModule()
# are called exactly once per class/module).
@atexit.register
def destroy_cached_debug_session():
if cached_debug_session:
cached_debug_session.tearDown()
class LLDBDebugSession(object):
@classmethod
def setup(cls):
BREAK_FOR_TESTING_FUNCTION_NAME = 'breakForTestingSummaryProviders'
cls.sbDebugger = lldb.SBDebugger.Create()
cls.sbDebugger.SetAsync(False)
cls.lldbWebKitTesterExecutable = str(os.environ['LLDB_WEBKIT_TESTER_EXECUTABLE'])
cls.sbTarget = cls.sbDebugger.CreateTarget(cls.lldbWebKitTesterExecutable)
assert cls.sbTarget
cls.sbTarget.BreakpointCreateByName(BREAK_FOR_TESTING_FUNCTION_NAME, cls.sbTarget.GetExecutable().GetFilename())
argv = None
envp = None
cls.sbProcess = cls.sbTarget.LaunchSimple(argv, envp, os.getcwd())
assert cls.sbProcess
assert cls.sbProcess.GetState() == lldb.eStateStopped
cls.sbThread = cls.sbProcess.GetThreadAtIndex(0)
assert cls.sbThread
# Frame 0 is the function with name BREAK_FOR_TESTING_FUNCTION_NAME. We want the frame of the caller of
# BREAK_FOR_TESTING_FUNCTION_NAME because it has all the interesting local variables we want to test.
cls.sbFrame = cls.sbThread.GetFrameAtIndex(1)
assert cls.sbFrame
@classmethod
def tearDown(cls):
cls.sbProcess.Kill()
class TestSummaryProviders(unittest.TestCase):
@classmethod
def shouldSkip(cls):
return not SystemHost().platform.is_mac()
@classmethod
def setUpClass(cls):
global cached_debug_session
if not cached_debug_session:
cached_debug_session = LLDBDebugSession()
cached_debug_session.setup()
@property
def _sbFrame(self):
return cached_debug_session.sbFrame
# The LLDB Python module does not work with Python multiprocessing and causes errors of the form:
# objc[76794]: +[__MDQuery initialize] may have been in progress in another thread when fork() was called.
# We cannot safely call it or ignore it in the fork() child process. Crashing instead.
# So, we run the following tests serially.
# MARK: WTFStringImpl_SummaryProvider test cases
def serial_test_WTFStringImpl_SummaryProvider_null_string(self):
summary = lldb_webkit.WTFStringImpl_SummaryProvider(self._sbFrame.FindVariable('aNullStringImpl'), {})
self.assertEqual(summary, "{ length = 0, is8bit = 1, contents = '' }")
def serial_test_WTFStringImpl_SummaryProvider_empty_string(self):
summary = lldb_webkit.WTFStringImpl_SummaryProvider(self._sbFrame.FindVariable('anEmptyStringImpl'), {})
self.assertEqual(summary, "{ length = 0, is8bit = 1, contents = '' }")
def serial_test_WTFStringImpl_SummaryProvider_8bit_string(self):
summary = lldb_webkit.WTFStringImpl_SummaryProvider(self._sbFrame.FindVariable('an8BitStringImpl'), {})
self.assertEqual(summary, "{ length = 8, is8bit = 1, contents = 'r\\xe9sum\\xe9' }")
def serial_test_WTFStringImpl_SummaryProvider_16bit_string(self):
summary = lldb_webkit.WTFStringImpl_SummaryProvider(self._sbFrame.FindVariable('a16BitStringImpl'), {})
self.assertEqual(summary, u"{ length = 13, is8bit = 0, contents = '\\u1680Cappuccino\\u1680\\x00' }")
# MARK: WTFString_SummaryProvider test cases
def serial_test_WTFString_SummaryProvider_null_string(self):
summary = lldb_webkit.WTFString_SummaryProvider(self._sbFrame.FindVariable('aNullString'), {})
self.assertEqual(summary, "{ length = 0, contents = '' }")
def serial_test_WTFString_SummaryProvider_empty_string(self):
summary = lldb_webkit.WTFString_SummaryProvider(self._sbFrame.FindVariable('anEmptyString'), {})
self.assertEqual(summary, "{ length = 0, contents = '' }")
def serial_test_WTFString_SummaryProvider_8bit_string(self):
summary = lldb_webkit.WTFString_SummaryProvider(self._sbFrame.FindVariable('an8BitString'), {})
self.assertEqual(summary, "{ length = 8, contents = 'r\\xe9sum\\xe9' }")
def serial_test_WTFString_SummaryProvider_16bit_string(self):
summary = lldb_webkit.WTFString_SummaryProvider(self._sbFrame.FindVariable('a16BitString'), {})
self.assertEqual(summary, u"{ length = 13, contents = '\\u1680Cappuccino\\u1680\\x00' }")
# MARK: WTFVector_SummaryProvider test cases
def serial_test_WTFVectorProvider_empty_vector(self):
variable = self._sbFrame.FindVariable('anEmptyVector');
summary = lldb_webkit.WTFVector_SummaryProvider(variable, {})
self.assertEqual(summary, "{ size = 0, capacity = 0 }")
def serial_test_WTFVectorProvider_vector_size_and_capacity(self):
variable = self._sbFrame.FindVariable('aVectorWithOneItem');
summary = lldb_webkit.WTFVector_SummaryProvider(variable, {})
self.assertEqual(summary, "{ size = 1, capacity = 16 }")
# MARK: WTFHashMap_SummaryProvider and WTFHashSet_SummaryProvider test cases
def serial_test_WTFHashMap_tablesize_and_size(self):
variable = self._sbFrame.FindVariable('hashMapOfInts')
summary = lldb_webkit.WTFHashMap_SummaryProvider(variable, {})
self.assertEqual(summary, "{ tableSize = 8, keyCount = 2 }")
def serial_test_WTFHashMap_of_vectors_tablesize_and_size(self):
variable = self._sbFrame.FindVariable('hashMapOfVectors')
summary = lldb_webkit.WTFHashMap_SummaryProvider(variable, {})
self.assertEqual(summary, "{ tableSize = 8, keyCount = 1 }")
def serial_test_WTFHashSet_tablesize_and_size(self):
variable = self._sbFrame.FindVariable('hashSetOfInts')
summary = lldb_webkit.WTFHashSet_SummaryProvider(variable, {})
self.assertEqual(summary, "{ tableSize = 8, keyCount = 1 }")
# MARK: WTFOptionSet_SummaryProvider test cases
def serial_test_WTFOptionSet_SummaryProvider_empty(self):
variable = self._sbFrame.FindVariable('exampleFlagsEmpty')
summary = lldb_webkit.WTFOptionSet_SummaryProvider(variable, {})
self.assertEqual(summary, "{ size = 0 }")
def serial_test_WTFOptionSet_SummaryProvider_simple(self):
variable = self._sbFrame.FindVariable('exampleFlagsSimple')
summary = lldb_webkit.WTFOptionSet_SummaryProvider(variable, {})
self.assertEqual(summary, "{ size = 3 }")
# MARK: WTFOptionSetProvider test cases
def serial_test_WTFOptionSetProvider_empty(self):
variable = self._sbFrame.FindVariable('exampleFlagsEmpty')
provider = lldb_webkit.WTFOptionSetProvider(variable, {})
self.assertEqual(provider.get_child_at_index(0), None)
def serial_test_WTFOptionSetProvider_simple(self):
variable = self._sbFrame.FindVariable('exampleFlagsSimple')
provider = lldb_webkit.WTFOptionSetProvider(variable, {})
self.assertEqual(provider.get_child_at_index(0).GetName(), 'A')
self.assertEqual(provider.get_child_at_index(0).GetValue(), '1')
self.assertEqual(provider.get_child_at_index(1).GetName(), 'C')
self.assertEqual(provider.get_child_at_index(1).GetValue(), '4')
self.assertEqual(provider.get_child_at_index(2).GetName(), 'D')
self.assertEqual(provider.get_child_at_index(2).GetValue(), '8')
def serial_test_WTFOptionSetProvider_aliased_flag(self):
variable = self._sbFrame.FindVariable('exampleFlagsAliasedFlag')
provider = lldb_webkit.WTFOptionSetProvider(variable, {})
self.assertEqual(provider.get_child_at_index(0).GetName(), 'A')
self.assertEqual(provider.get_child_at_index(0).GetValue(), '1')
self.assertEqual(provider.get_child_at_index(1).GetName(), 'D')
self.assertEqual(provider.get_child_at_index(1).GetValue(), '8')