1#!/usr/bin/python
2# Copyright 2017 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""unittest for result_info.py
7"""
8
9import copy
10import os
11import shutil
12import tempfile
13import unittest
14
15import common
16from autotest_lib.client.bin.result_tools import result_info
17from autotest_lib.client.bin.result_tools import unittest_lib
18from autotest_lib.client.bin.result_tools import utils_lib
19
20
21_SIZE = 100
22_EXPECTED_SUMMARY = {
23    '': {utils_lib.ORIGINAL_SIZE_BYTES: 13 * _SIZE,
24         utils_lib.TRIMMED_SIZE_BYTES: 4 * _SIZE,
25         utils_lib.DIRS: [
26                 {'file1': {utils_lib.ORIGINAL_SIZE_BYTES: _SIZE}},
27                 {'folder1': {utils_lib.ORIGINAL_SIZE_BYTES: 11 * _SIZE,
28                              utils_lib.TRIMMED_SIZE_BYTES: 2 * _SIZE,
29                              utils_lib.DIRS: [
30                                {'file2': {
31                                    utils_lib.ORIGINAL_SIZE_BYTES: 10 * _SIZE,
32                                    utils_lib.TRIMMED_SIZE_BYTES: _SIZE}},
33                                {'file3': {
34                                  utils_lib.ORIGINAL_SIZE_BYTES: _SIZE}}]}},
35                 {'folder2': {utils_lib.ORIGINAL_SIZE_BYTES: _SIZE,
36                              utils_lib.DIRS:
37                                [{'file2': {
38                                    utils_lib.ORIGINAL_SIZE_BYTES: _SIZE}
39                                  }],
40                             }
41                  }
42            ]
43        }
44    }
45
46_EXPECTED_SINGLE_FILE_SUMMARY = {
47    '': {utils_lib.ORIGINAL_SIZE_BYTES: unittest_lib.SIZE,
48         utils_lib.DIRS: [
49                 {'file1': {utils_lib.ORIGINAL_SIZE_BYTES: unittest_lib.SIZE}},
50                 ]
51         }
52    }
53
54class ResultInfoUnittest(unittest.TestCase):
55    """Test class for ResultInfo.
56    """
57
58    def setUp(self):
59        """Setup directory for test."""
60        self.test_dir = tempfile.mkdtemp()
61
62    def tearDown(self):
63        """Cleanup the test directory."""
64        shutil.rmtree(self.test_dir, ignore_errors=True)
65
66    def testLoadJson(self):
67        """Test method load_summary_json_file and related update methods."""
68        summary_file = os.path.join(self.test_dir, 'summary.json')
69        result_info.save_summary(_EXPECTED_SUMMARY, summary_file)
70        summary = result_info.load_summary_json_file(summary_file)
71
72        self.assertEqual(_EXPECTED_SUMMARY, summary,
73                         'Failed to match the loaded json file.')
74        # Save the json of the new summary, confirm it matches the old one.
75        summary_file_new = os.path.join(self.test_dir, 'summary_new.json')
76        result_info.save_summary(summary, summary_file_new)
77        summary_new = result_info.load_summary_json_file(summary_file_new)
78        self.assertEqual(
79                _EXPECTED_SUMMARY, summary_new,
80                'Failed to match the loaded json file after it is saved again.')
81
82        # Validate the details of result_info.
83        self.assertEqual(summary.path, self.test_dir)
84        self.assertEqual(summary.get_file('file1').path,
85                         os.path.join(self.test_dir, 'file1'))
86        self.assertEqual(summary.get_file('folder1').get_file('file2').path,
87                         os.path.join(self.test_dir, 'folder1', 'file2'))
88
89        # Validate the details of a deep copy of result_info.
90        new_summary = copy.deepcopy(summary)
91        # Modify old summary, to make sure the clone is not changed.
92        summary._path = None
93        summary.get_file('file1')._path = None
94        summary.get_file('file1').original_size = 0
95        summary.get_file('folder1').get_file('file2')._path = None
96
97        self.assertEqual(new_summary.path, self.test_dir)
98        self.assertEqual(new_summary.get_file('file1').path,
99                         os.path.join(self.test_dir, 'file1'))
100        self.assertEqual(new_summary.get_file('file1').original_size, _SIZE)
101        self.assertEqual(id(new_summary.get_file('file1')._parent_result_info),
102                         id(new_summary))
103        self.assertNotEqual(id(new_summary), id(summary))
104        self.assertEqual(new_summary.get_file('folder1').get_file('file2').path,
105                         os.path.join(self.test_dir, 'folder1', 'file2'))
106
107    def testInit(self):
108        """Test __init__ method fails when both name and original_info are set.
109        """
110        self.assertRaises(result_info.ResultInfoError, result_info.ResultInfo,
111                          'parent_dir', 'file_name', None,
112                          {'name': 'file_name'})
113
114    def testUpdateSize(self):
115        """Test sizes updated in all parent nodes after leaf node is updated.
116        """
117        summary_file = os.path.join(self.test_dir, 'summary.json')
118        result_info.save_summary(_EXPECTED_SUMMARY, summary_file)
119        summary = result_info.load_summary_json_file(summary_file)
120        file2 = summary.get_file('folder1').get_file('file2')
121        file2.trimmed_size = 2 * _SIZE
122
123        # Check all parent result info have size updated.
124        self.assertEqual(file2.trimmed_size, 2 * _SIZE)
125        self.assertEqual(summary.get_file('folder1').trimmed_size, 3 * _SIZE)
126        self.assertEqual(summary.trimmed_size, 5 * _SIZE)
127
128        file2.original_size = 11 * _SIZE
129        self.assertEqual(summary.get_file('folder1').original_size, 12 * _SIZE)
130        self.assertEqual(summary.original_size, 14 * _SIZE)
131
132        file2.collected_size = 20 * _SIZE
133        self.assertEqual(summary.get_file('folder1').collected_size, 21 * _SIZE)
134        self.assertEqual(summary.collected_size, 23 * _SIZE)
135
136    def TestBuildFromPath_SingleFile(self):
137        """Test method build_from_path for a single file."""
138        file1 = os.path.join(self.test_dir, 'file1')
139        unittest_lib.create_file(file1)
140        summary = result_info.ResultInfo.build_from_path(file1)
141        self.assertEqual(_EXPECTED_SINGLE_FILE_SUMMARY, summary)
142
143
144# this is so the test can be run in standalone mode
145if __name__ == '__main__':
146    """Main"""
147    unittest.main()
148