def testSuffixCanExtendPatternedHistograms(self): patterned_suffix = (""" <histogram-configuration> <histograms> <histogram name="Test{Version}" units="things" expires_after="2017-10-16"> <owner>[email protected]</owner> <summary> Sample description. </summary> <token key="Version"> <variant name=".First"/> <variant name=".Last"/> </token> </histogram> </histograms> <histogram_suffixes_list> <histogram_suffixes name="ExtendPatternedHist" separator="."> <suffix name="Found" label="Extending patterned histograms."/> <affected-histogram name="Test.First"/> <affected-histogram name="Test.Last"/> </histogram_suffixes> </histogram_suffixes_list> </histogram-configuration>""") # Only when the histogram is first extended by the token, can the # histogram_suffixes find those affected histograms. histograms_dict, had_errors = extract_histograms.ExtractHistogramsFromDom( xml.dom.minidom.parseString(patterned_suffix)) self.assertFalse(had_errors) self.assertIn('Test.First.Found', histograms_dict) self.assertIn('Test.Last.Found', histograms_dict)
def testBaseHistograms(self): histograms, had_errors = extract_histograms.ExtractHistogramsFromDom( xml.dom.minidom.parseString(TEST_BASE_HISTOGRAM_XML_CONTENT)) self.assertFalse(had_errors) # Base histograms are implicitly marked as obsolete. self.assertIn('obsolete', histograms['Test.Base']) self.assertIn('obsolete', histograms['Test.Base.Obsolete']) # Other histograms shouldn't be implicitly marked as obsolete. self.assertNotIn('obsolete', histograms['Test.NotBase.Explicit']) self.assertNotIn('obsolete', histograms['Test.NotBase.Implicit']) # Suffixes applied to base histograms shouldn't be marked as obsolete... self.assertNotIn('obsolete', histograms['Test.Base.NonBaseSuffix']) # ... unless the suffix is marked as obsolete, self.assertIn('obsolete', histograms['Test.Base.ObsoleteSuffix']) # ... or the suffix is a base suffix, self.assertIn('obsolete', histograms['Test.Base.BaseSuffix']) # ... or the base histogram is marked as obsolete, self.assertIn('obsolete', histograms['Test.Base.Obsolete.BaseSuffix']) self.assertIn('obsolete', histograms['Test.Base.Obsolete.NonBaseSuffix']) self.assertIn('obsolete', histograms['Test.Base.Obsolete.ObsoleteSuffix']) # It should be possible to have multiple levels of suffixes for base # histograms. self.assertNotIn('obsolete', histograms['Test.Base.BaseSuffix.One']) self.assertNotIn('obsolete', histograms['Test.Base.BaseSuffix.Two']) self.assertNotIn('obsolete', histograms['Test.Base.NonBaseSuffix.One']) self.assertNotIn('obsolete', histograms['Test.Base.NonBaseSuffix.Two'])
def _GenerateFileContent(descriptions, branch_file_content, mstone_file_content, header_filename, namespace): """Generates header file containing array with hashes of expired histograms. Args: descriptions: Combined histogram descriptions. branch_file_content: Content of file with base date. mstone_file_content: Content of file with milestone information. header_filename: A filename of the generated header file. namespace: A namespace to contain generated array. Raises: Error if there is an error in input xml files. """ histograms, had_errors = ( extract_histograms.ExtractHistogramsFromDom(descriptions)) if had_errors: raise Error("Error parsing inputs.") base_date = _GetBaseDate(branch_file_content, _DATE_FILE_RE) base_date -= datetime.timedelta(weeks=_EXPIRE_GRACE_WEEKS) current_milestone = _GetCurrentMilestone( mstone_file_content, _CURRENT_MILESTONE_RE) current_milestone -= _EXPIRE_GRACE_MSTONES expired_histograms_names = _GetExpiredHistograms( histograms, base_date, current_milestone) expired_histograms_map = _GetHashToNameMap(expired_histograms_names) header_file_content = _GenerateHeaderFileContent( header_filename, namespace, expired_histograms_map) return header_file_content
def _GenerateFile(arguments): """Generates header file containing array with hashes of expired histograms. Args: arguments: An object with the following attributes: arguments.inputs: A list of xml files with histogram descriptions. arguments.header_filename: A filename of the generated header file. arguments.namespace: A namespace to contain generated array. arguments.hash_datatype: Datatype of histogram names' hash. arguments.output_dir: A directory to put the generated file. Raises: Error if there is an error in input xml files. """ descriptions = merge_xml.MergeFiles(arguments.inputs) histograms, had_errors = ( extract_histograms.ExtractHistogramsFromDom(descriptions)) if had_errors: raise Error("Error parsing inputs.") with open(arguments.major_branch_date_filepath, "r") as date_file: file_content = date_file.read() base_date = _GetBaseDate(file_content, _DATE_FILE_PATTERN) expired_histograms_names = _GetExpiredHistograms(histograms, base_date) expired_histograms_map = _GetHashToNameMap(expired_histograms_names) header_file_content = _GenerateHeaderFileContent(arguments.header_filename, arguments.namespace, expired_histograms_map) with open(os.path.join(arguments.output_dir, arguments.header_filename), "w") as generated_file: generated_file.write(header_file_content)
def testComponentExtraction(self): """Checks that components are successfully extracted from histograms.""" histogram = xml.dom.minidom.parseString(""" <histogram-configuration> <histograms> <histogram name="Coffee" expires_after="2022-01-01"> <owner>[email protected]</owner> <summary>An ode to coffee.</summary> <component>Liquid>Hot</component> <component>Caffeine</component> </histogram> </histograms> <histogram_suffixes_list> <histogram_suffixes name="Brand" separator="."> <suffix name="Dunkies" label="The coffee is from Dunkin."/> <affected-histogram name="Coffee"/> </histogram_suffixes> </histogram_suffixes_list> </histogram-configuration> """) histograms, _ = extract_histograms.ExtractHistogramsFromDom(histogram) self.assertEqual(histograms['Coffee']['components'], ['Liquid>Hot', 'Caffeine']) self.assertEqual(histograms['Coffee.Dunkies']['components'], ['Liquid>Hot', 'Caffeine'])
def main(): doc = merge_xml.MergeFiles(histogram_paths.ALL_XMLS) histograms, had_errors = extract_histograms.ExtractHistogramsFromDom(doc) if had_errors: raise Error("Error parsing inputs.") names = extract_histograms.ExtractNames(histograms) for name in names: print name
def readAllXmlHistograms(): """Parses all histogram names defined in |histogram_paths.ALL_XMLS|. Returns: A set containing the parsed histogram names. """ merged = merge_xml.MergeFiles(histogram_paths.ALL_XMLS) histograms, _ = extract_histograms.ExtractHistogramsFromDom(merged) return set(extract_histograms.ExtractNames(histograms))
def testExpiryFormat(self): chrome_histogram_pattern = """<histogram-configuration> <histograms> <histogram name="Histogram.Name"{}> <owner>[email protected]</owner> <summary>Summary</summary> </histogram> </histograms> </histogram-configuration> """ chrome_histogram_correct_expiry_date = chrome_histogram_pattern.format( ' expires_after="2211-11-22"') _, had_errors = extract_histograms.ExtractHistogramsFromDom( xml.dom.minidom.parseString(chrome_histogram_correct_expiry_date)) self.assertFalse(had_errors) chrome_histogram_wrong_expiry_date_format = chrome_histogram_pattern.format( ' expires_after="2211/11/22"') _, had_errors = extract_histograms.ExtractHistogramsFromDom( xml.dom.minidom.parseString( chrome_histogram_wrong_expiry_date_format)) self.assertTrue(had_errors) chrome_histogram_wrong_expiry_date_value = chrome_histogram_pattern.format( ' expires_after="2211-22-11"') _, had_errors = extract_histograms.ExtractHistogramsFromDom( xml.dom.minidom.parseString( chrome_histogram_wrong_expiry_date_value)) self.assertTrue(had_errors) chrome_histogram_correct_expiry_milestone = chrome_histogram_pattern.format( ' expires_after="M22"') _, had_errors = extract_histograms.ExtractHistogramsFromDom( xml.dom.minidom.parseString( chrome_histogram_correct_expiry_milestone)) self.assertFalse(had_errors) chrome_histogram_wrong_expiry_milestone = chrome_histogram_pattern.format( ' expires_after="22"') _, had_errors = extract_histograms.ExtractHistogramsFromDom( xml.dom.minidom.parseString( chrome_histogram_wrong_expiry_milestone)) self.assertTrue(had_errors) chrome_histogram_wrong_expiry_milestone = chrome_histogram_pattern.format( ' expires_after="MM22"') _, had_errors = extract_histograms.ExtractHistogramsFromDom( xml.dom.minidom.parseString( chrome_histogram_wrong_expiry_milestone)) self.assertTrue(had_errors) chrome_histogram_no_expiry = chrome_histogram_pattern.format('') _, had_errors = extract_histograms.ExtractHistogramsFromDom( xml.dom.minidom.parseString(chrome_histogram_no_expiry)) self.assertFalse(had_errors)
def testNewSuffixWithoutLabel(self): suffix_without_label = xml.dom.minidom.parseString(""" <histogram-configuration> <histogram_suffixes_list> <histogram_suffixes name="Suffixes" separator="."> <suffix base="true" name="BaseSuffix"/> </histogram_suffixes> </histogram_suffixes_list> </histogram-configuration> """) _, have_errors = extract_histograms.ExtractHistogramsFromDom( suffix_without_label) self.assertTrue(have_errors)
def testExpiryDateExtraction(self): chrome_histogram_pattern = """<histogram-configuration> <histograms> <histogram name="Histogram.Name"{}> <owner>[email protected]</owner> <summary>Summary</summary> </histogram> </histograms> </histogram-configuration> """ date_str = '2211-11-22' chrome_histogram_correct_expiry_date = chrome_histogram_pattern.format( ' expires_after="{}"'.format(date_str)) histograms, _ = extract_histograms.ExtractHistogramsFromDom( xml.dom.minidom.parseString(chrome_histogram_correct_expiry_date)) histogram_content = histograms['Histogram.Name'] self.assertIn('expires_after', histogram_content) self.assertEqual(date_str, histogram_content['expires_after']) milestone_str = 'M22' chrome_histogram_correct_expiry_milestone = chrome_histogram_pattern.format( ' expires_after="{}"'.format(milestone_str)) histograms, _ = extract_histograms.ExtractHistogramsFromDom( xml.dom.minidom.parseString( chrome_histogram_correct_expiry_milestone)) histogram_content = histograms['Histogram.Name'] self.assertIn('expires_after', histogram_content) self.assertEqual(milestone_str, histogram_content['expires_after']) chrome_histogram_no_expiry = chrome_histogram_pattern.format('') histograms, _ = extract_histograms.ExtractHistogramsFromDom( xml.dom.minidom.parseString(chrome_histogram_no_expiry)) histogram_content = histograms['Histogram.Name'] self.assertNotIn('expires_after', histogram_content)
def get_names(xml_files): """Returns all histogram names generated from a list of xml files. Args: xml_files: A list of open file objects containing histogram definitions. Returns: A tuple of (names, obsolete names), where the obsolete names is a subset of all names. """ doc = merge_xml.MergeFiles(files=xml_files) histograms, had_errors = extract_histograms.ExtractHistogramsFromDom(doc) if had_errors: raise ValueError("Error parsing inputs.") names = set(extract_histograms.ExtractNames(histograms)) obsolete_names = set(extract_histograms.ExtractObsoleteNames(histograms)) return (names, obsolete_names)
def main(args): # Extract all histograms into a dict. doc = merge_xml.MergeFiles(filenames=histogram_paths.ALL_XMLS, should_expand_owners=True) histograms, had_errors = extract_histograms.ExtractHistogramsFromDom(doc) if had_errors: raise ValueError("Error parsing inputs.") # Construct a dom tree that is similar to the normal histograms.xml so that # we can use histogram_configuration_model to pretty print it. doc = xml.dom.minidom.Document() configuration = doc.createElement('histogram-configuration') histograms_node = doc.createElement('histograms') for name, histogram in histograms.items(): if re.match(args.pattern, name): histograms_node.appendChild( ConstructHistogram(doc, name, histogram)) configuration.appendChild(histograms_node) doc.appendChild(configuration) print(histogram_configuration_model.PrettifyTree(doc))
def testSuffixObsoletion(self): histograms, had_errors = extract_histograms.ExtractHistogramsFromDom( xml.dom.minidom.parseString(TEST_SUFFIX_OBSOLETION_XML_CONTENT)) self.assertFalse(had_errors) # Obsolete on suffixes doesn't affect the source histogram self.assertNotIn('obsolete', histograms['Test.Test1']) self.assertNotIn('obsolete', histograms['Test.Test2']) self.assertNotIn('obsolete', histograms['Test.Test1_NonObsolete1']) self.assertNotIn('obsolete', histograms['Test.Test1_NonObsolete2']) self.assertNotIn('obsolete', histograms['Test.Test2_NonObsolete1']) self.assertNotIn('obsolete', histograms['Test.Test2_NonObsolete2']) self.assertIn('obsolete', histograms['Test.Test1_ObsoleteSuffixGroup1']) self.assertIn('obsolete', histograms['Test.Test1_ObsoleteSuffixGroup2']) # Obsolete suffixes should apply to individual suffixes and not their group. self.assertIn('obsolete', histograms['Test.Test2_ObsoleteSuffixNonObsoleteGroup1']) self.assertNotIn( 'obsolete', histograms['Test.Test2_NonObsoleteSuffixNonObsoleteGroup2']) self.assertEqual( 'This suffix is obsolete', histograms['Test.Test2_ObsoleteSuffixNonObsoleteGroup1'] ['obsolete']) # Obsolete suffix reasons should overwrite the suffix group's obsoletion # reason. self.assertIn('obsolete', histograms['Test.Test2_ObsoleteSuffixObsoleteGroup1']) self.assertIn('obsolete', histograms['Test.Test2_NonObsoleteSuffixObsoleteGroup2']) self.assertEqual( 'This suffix is obsolete', histograms['Test.Test2_ObsoleteSuffixObsoleteGroup1']['obsolete']) self.assertEqual( 'This suffix group is obsolete', histograms['Test.Test2_NonObsoleteSuffixObsoleteGroup2'] ['obsolete'])
def testNewHistogramWithEnum(self): histogram_with_enum = xml.dom.minidom.parseString(""" <histogram-configuration> <enums> <enum name="MyEnumType"> <summary>This is an example enum type</summary> <int value="1" label="FIRST_VALUE">This is the first value.</int> <int value="2" label="SECOND_VALUE">This is the second value.</int> </enum> </enums> <histograms> <histogram name="Test.Histogram.Enum" enum="MyEnumType"> <owner>[email protected]</owner> <summary> This is a summary </summary> </histogram> </histograms> </histogram-configuration> """) _, have_errors = extract_histograms.ExtractHistogramsFromDom( histogram_with_enum) self.assertFalse(have_errors)
def main(): doc = merge_xml.MergeFiles(histogram_paths.ALL_XMLS) _, errors = extract_histograms.ExtractHistogramsFromDom(doc) sys.exit(errors)
def get_names(xml_files): doc = merge_xml.MergeFiles(files=xml_files) histograms, had_errors = extract_histograms.ExtractHistogramsFromDom(doc) if had_errors: raise Error("Error parsing inputs.") return extract_histograms.ExtractNames(histograms)
def main(): doc = merge_xml.MergeFiles(histogram_paths.ALL_XMLS, should_expand_owners=True) _, errors = extract_histograms.ExtractHistogramsFromDom(doc) sys.exit(errors)