12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#!/usr/bin/env python
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved.
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# found in the LICENSE file.
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import cStringIO
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import logging
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import os
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import sys
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import textwrap
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import unittest
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochBASE_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochsys.path.append(BASE_PATH)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochfrom lib.bucket import Bucket
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochfrom lib.ordered_dict import OrderedDict
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochfrom lib.policy import Policy
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochfrom lib.symbol import SymbolMappingCache
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochfrom lib.symbol import FUNCTION_SYMBOLS, SOURCEFILE_SYMBOLS, TYPEINFO_SYMBOLS
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport subcommands
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class SymbolMappingCacheTest(unittest.TestCase):
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  class MockBucketSet(object):
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __init__(self, addresses):
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self._addresses = addresses
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    def iter_addresses(self, symbol_type):  # pylint: disable=W0613
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for address in self._addresses:
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        yield address
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  class MockSymbolFinder(object):
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __init__(self, mapping):
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self._mapping = mapping
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def find(self, address_list):
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      result = OrderedDict()
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      for address in address_list:
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        result[address] = self._mapping[address]
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return result
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  _TEST_FUNCTION_CACHE = textwrap.dedent("""\
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      1 0x0000000000000001
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      7fc33eebcaa4 __gnu_cxx::new_allocator::allocate
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      7fc33ef69242 void DispatchToMethod
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      """)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  _EXPECTED_TEST_FUNCTION_CACHE = textwrap.dedent("""\
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      1 0x0000000000000001
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      7fc33eebcaa4 __gnu_cxx::new_allocator::allocate
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      7fc33ef69242 void DispatchToMethod
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      2 0x0000000000000002
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      7fc33ef7bc3e std::map::operator[]
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      7fc34411f9d5 WTF::RefCounted::operator new
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      """)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  _TEST_FUNCTION_ADDRESS_LIST1 = [
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      0x1, 0x7fc33eebcaa4, 0x7fc33ef69242]
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  _TEST_FUNCTION_ADDRESS_LIST2 = [
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      0x1, 0x2, 0x7fc33eebcaa4, 0x7fc33ef69242, 0x7fc33ef7bc3e, 0x7fc34411f9d5]
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  _TEST_FUNCTION_DICT = {
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      0x1: '0x0000000000000001',
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      0x2: '0x0000000000000002',
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      0x7fc33eebcaa4: '__gnu_cxx::new_allocator::allocate',
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      0x7fc33ef69242: 'void DispatchToMethod',
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      0x7fc33ef7bc3e: 'std::map::operator[]',
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      0x7fc34411f9d5: 'WTF::RefCounted::operator new',
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def test_update(self):
757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    symbol_mapping_cache = SymbolMappingCache()
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cache_f = cStringIO.StringIO()
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cache_f.write(self._TEST_FUNCTION_CACHE)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # No update from self._TEST_FUNCTION_CACHE
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    symbol_mapping_cache.update(
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        FUNCTION_SYMBOLS,
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.MockBucketSet(self._TEST_FUNCTION_ADDRESS_LIST1),
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.MockSymbolFinder(self._TEST_FUNCTION_DICT), cache_f)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for address in self._TEST_FUNCTION_ADDRESS_LIST1:
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self.assertEqual(self._TEST_FUNCTION_DICT[address],
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       symbol_mapping_cache.lookup(FUNCTION_SYMBOLS, address))
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertEqual(self._TEST_FUNCTION_CACHE, cache_f.getvalue())
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    # Update to self._TEST_FUNCTION_ADDRESS_LIST2
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    symbol_mapping_cache.update(
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        FUNCTION_SYMBOLS,
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.MockBucketSet(self._TEST_FUNCTION_ADDRESS_LIST2),
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        self.MockSymbolFinder(self._TEST_FUNCTION_DICT), cache_f)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for address in self._TEST_FUNCTION_ADDRESS_LIST2:
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      self.assertEqual(self._TEST_FUNCTION_DICT[address],
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       symbol_mapping_cache.lookup(FUNCTION_SYMBOLS, address))
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertEqual(self._EXPECTED_TEST_FUNCTION_CACHE, cache_f.getvalue())
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class PolicyTest(unittest.TestCase):
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  class MockSymbolMappingCache(object):
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    def __init__(self):
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      self._symbol_caches = {
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          FUNCTION_SYMBOLS: {},
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          SOURCEFILE_SYMBOLS: {},
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          TYPEINFO_SYMBOLS: {},
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          }
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    def add(self, symbol_type, address, symbol):
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      self._symbol_caches[symbol_type][address] = symbol
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    def lookup(self, symbol_type, address):
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      symbol = self._symbol_caches[symbol_type].get(address)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return symbol if symbol else '0x%016x' % address
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  _TEST_POLICY = textwrap.dedent("""\
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      {
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "components": [
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "second",
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "mmap-v8",
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "malloc-v8",
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "malloc-WebKit",
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "mmap-catch-all",
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "malloc-catch-all"
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ],
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "rules": [
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          {
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "name": "second",
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "stacktrace": "optional",
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "allocator": "optional"
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          },
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          {
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "name": "mmap-v8",
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "stacktrace": ".*v8::.*",
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "allocator": "mmap"
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          },
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          {
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "name": "malloc-v8",
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "stacktrace": ".*v8::.*",
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "allocator": "malloc"
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          },
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          {
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "name": "malloc-WebKit",
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "stacktrace": ".*WebKit::.*",
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "allocator": "malloc"
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          },
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          {
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "name": "mmap-catch-all",
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "stacktrace": ".*",
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "allocator": "mmap"
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          },
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          {
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "name": "malloc-catch-all",
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "stacktrace": ".*",
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            "allocator": "malloc"
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ],
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "version": "POLICY_DEEP_3"
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      """)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def test_load(self):
1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    policy = Policy.parse(cStringIO.StringIO(self._TEST_POLICY), 'json')
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertTrue(policy)
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertEqual('POLICY_DEEP_3', policy.version)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def test_find(self):
1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    policy = Policy.parse(cStringIO.StringIO(self._TEST_POLICY), 'json')
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertTrue(policy)
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    symbol_mapping_cache = self.MockSymbolMappingCache()
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    symbol_mapping_cache.add(FUNCTION_SYMBOLS, 0x1212, 'v8::create')
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    symbol_mapping_cache.add(FUNCTION_SYMBOLS, 0x1381, 'WebKit::create')
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    bucket1 = Bucket([0x1212, 0x013], 'malloc', 0x29492, '_Z')
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bucket1.symbolize(symbol_mapping_cache)
1777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    bucket2 = Bucket([0x18242, 0x1381], 'malloc', 0x9492, '_Z')
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bucket2.symbolize(symbol_mapping_cache)
1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    bucket3 = Bucket([0x18242, 0x181], 'malloc', 0x949, '_Z')
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bucket3.symbolize(symbol_mapping_cache)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    self.assertEqual('malloc-v8', policy.find_malloc(bucket1))
1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    self.assertEqual('malloc-WebKit', policy.find_malloc(bucket2))
1847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    self.assertEqual('malloc-catch-all', policy.find_malloc(bucket3))
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class BucketsCommandTest(unittest.TestCase):
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  def test(self):
1897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    BUCKETS_PATH = os.path.join(BASE_PATH, 'tests', 'output', 'buckets')
1907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    with open(BUCKETS_PATH) as output_f:
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      expected = output_f.read()
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    out = cStringIO.StringIO()
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    HEAP_PATH = os.path.join(BASE_PATH, 'tests', 'data', 'heap.01234.0001.heap')
1967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    subcommand = subcommands.BucketsCommand()
1977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    returncode = subcommand.do(['buckets', HEAP_PATH], out)
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.assertEqual(0, returncode)
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    self.assertEqual(expected, out.getvalue())
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class UploadCommandTest(unittest.TestCase):
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  def test(self):
2047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    MOCK_GSUTIL_PATH = os.path.join(BASE_PATH, 'tests', 'mock_gsutil.py')
2057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    HEAP_PATH = os.path.join(BASE_PATH, 'tests', 'data', 'heap.01234.0001.heap')
2067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    subcommand = subcommands.UploadCommand()
2077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    returncode = subcommand.do([
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        'upload',
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         '--gsutil',
2107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        MOCK_GSUTIL_PATH,
2117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        HEAP_PATH,
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        'gs://test-storage/'])
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertEqual(0, returncode)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)if __name__ == '__main__':
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  logging.basicConfig(
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      level=logging.DEBUG if '-v' in sys.argv else logging.ERROR,
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      format='%(levelname)5s %(filename)15s(%(lineno)3d): %(message)s')
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unittest.main()
221