1# Copyright 2014 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5from telemetry import value as value_module
6from telemetry.value import list_of_string_values
7from telemetry.value import none_values
8
9
10class StringValue(value_module.Value):
11  def __init__(self, page, name, units, value, important=True,
12               description=None, none_value_reason=None):
13    """A single value (float, integer or string) result from a test.
14
15    A test that output a hash of the content in a page might produce a
16    string value:
17       StringValue(page, 'page_hash', 'hash', '74E377FF')
18    """
19    super(StringValue, self).__init__(page, name, units, important, description)
20    assert value is None or isinstance(value, basestring)
21    none_values.ValidateNoneValueReason(value, none_value_reason)
22    self.value = value
23    self.none_value_reason = none_value_reason
24
25  def __repr__(self):
26    if self.page:
27      page_name = self.page.url
28    else:
29      page_name = None
30    return 'StringValue(%s, %s, %s, %s, important=%s, description=%s)' % (
31      page_name,
32      self.name,
33      self.units,
34      self.value,
35      self.important,
36      self.description)
37
38  def GetBuildbotDataType(self, output_context):
39    if self._IsImportantGivenOutputIntent(output_context):
40      return 'default'
41    return 'unimportant'
42
43  def GetBuildbotValue(self):
44    # Buildbot's print_perf_results method likes to get lists for all values,
45    # even when they are scalar, so list-ize the return value.
46    return [self.value]
47
48  def GetRepresentativeNumber(self):
49    return self.value
50
51  def GetRepresentativeString(self):
52    return str(self.value)
53
54  @staticmethod
55  def GetJSONTypeName():
56    return 'string'
57
58  def AsDict(self):
59    d = super(StringValue, self).AsDict()
60    d['value'] = self.value
61
62    if self.none_value_reason is not None:
63      d['none_value_reason'] = self.none_value_reason
64
65    return d
66
67  @staticmethod
68  def FromDict(value_dict, page_dict):
69    kwargs = value_module.Value.GetConstructorKwArgs(value_dict, page_dict)
70    kwargs['value'] = value_dict['value']
71
72    if 'none_value_reason' in value_dict:
73      kwargs['none_value_reason'] = value_dict['none_value_reason']
74
75    return StringValue(**kwargs)
76
77  @classmethod
78  def MergeLikeValuesFromSamePage(cls, values):
79    assert len(values) > 0
80    v0 = values[0]
81    return cls._MergeLikeValues(values, v0.page, v0.name)
82
83  @classmethod
84  def MergeLikeValuesFromDifferentPages(cls, values,
85                                        group_by_name_suffix=False):
86    assert len(values) > 0
87    v0 = values[0]
88    name = v0.name_suffix if group_by_name_suffix else v0.name
89    return cls._MergeLikeValues(values, None, name)
90
91  @classmethod
92  def _MergeLikeValues(cls, values, page, name):
93    v0 = values[0]
94    merged_value = [v.value for v in values]
95    none_value_reason = None
96    if None in merged_value:
97      merged_value = None
98      none_value_reason = none_values.MERGE_FAILURE_REASON
99    return list_of_string_values.ListOfStringValues(
100        page, name, v0.units, merged_value, important=v0.important,
101        none_value_reason=none_value_reason)
102