def testExpandOwnersWithoutOwnersFromFile(self): """Checks that an error is raised when no owners can be derived.""" absolute_path = _MakeOwnersFile('empty_OWNERS', self.temp_dir) src_relative_path = _GetSrcRelativePath(absolute_path) with open(absolute_path, 'w') as owners_file: owners_file.write('') # Write to the file so that it exists. histograms_without_owners_from_file = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <owner>{}</owner> <summary>I like coffee.</summary> </histogram> </histograms> """.format(src_relative_path)) with self.assertRaisesRegexp( expand_owners.Error, r'No emails could be derived from .*empty_OWNERS\.'): expand_owners.ExpandHistogramsOWNERS( histograms_without_owners_from_file) with self.assertRaisesRegexp( expand_owners.Error, r'The file at .*src/medium/medium/roast/OWNERS does not exist\.' ): expand_owners.ExpandHistogramsOWNERS( histograms_with_fake_file_path)
def testExpandOwnersWithSameOwners(self): """ Checks that no error is raised when all owners in a file are already in <owner> elements. """ absolute_path = _MakeOwnersFile('same_OWNERS', self.temp_dir) src_relative_path = _GetSrcRelativePath(absolute_path) with open(absolute_path, 'w') as owners_file: owners_file.write( '*****@*****.**') # Write to the file so that it exists. histograms_string = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <owner>{}</owner> <summary>I like coffee.</summary> </histogram> </histograms> """.format(src_relative_path)) self.assertEqual( expand_owners.ExpandHistogramsOWNERS(histograms_string), [])
def MergeTrees(trees, should_expand_owners): """Merges a list of histograms.xml DOM trees. Args: trees: A list of histograms.xml DOM trees. should_expand_owners: Whether we want to expand owners for histograms. Returns: A merged DOM tree. """ doc = xml.dom.minidom.Document() doc.appendChild( MakeNodeWithChildren( doc, 'histogram-configuration', # This can result in the merged document having multiple <enums> and # similar sections, but scripts ignore these anyway. GetEnumsNodes(doc, trees) + # Sort the <histogram> and <histogram_suffixes> nodes by name and # return the combined nodes. CombineHistogramsSorted(doc, trees))) # After using the unsafe version of appendChild, we see a regression when # pretty-printing the merged |doc|. This might because the unsafe appendChild # doesn't build indexes for later lookup. And thus, we need to convert the # merged |doc| to a xml string and convert it back to force it to build # indexes for the merged |doc|. doc = xml.dom.minidom.parseString(doc.toxml()) # Only perform fancy operations after |doc| becomes stable. This helps improve # the runtime perforamnce. if should_expand_owners: for histograms in doc.getElementsByTagName('histograms'): expand_owners.ExpandHistogramsOWNERS(histograms) return doc
def testExpandOwnersUsesMetadataOverOwners(self): """Checks that DIR_METADATA is used if available""" with open(os.path.join(self.temp_dir, 'DIR_METADATA'), "w+") as md: md.write("\n".join(['monorail {', 'component: "Bees"', '}'])) absolute_path = _MakeOwnersFile('simple_OWNERS', self.temp_dir) with open(absolute_path, 'w') as owners_file: owners_file.write('\n'.join( ['*****@*****.**', _DEFAULT_COMPONENT, '*****@*****.**'])) self.maxDiff = None src_relative_path = _GetSrcRelativePath(absolute_path) histograms = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <owner>{path}</owner> <summary>I like coffee.</summary> </histogram> <histogram name="Maple.Syrup" units="units"> <owner>[email protected]</owner> <owner>{path}</owner> <owner>[email protected]</owner> <summary>I like maple syrup, too.</summary> </histogram> </histograms> """.format(path=src_relative_path)) expected_histograms = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <owner>[email protected]</owner> <owner>[email protected]</owner> <summary>I like coffee.</summary> <component>Bees</component> </histogram> <histogram name="Maple.Syrup" units="units"> <owner>[email protected]</owner> <owner>[email protected]</owner> <owner>[email protected]</owner> <owner>[email protected]</owner> <summary>I like maple syrup, too.</summary> <component>Bees</component> </histogram> </histograms> """) expand_owners.ExpandHistogramsOWNERS(histograms) self.assertMultiLineEqual(histograms.toxml(), expected_histograms.toxml())
def testExpandOwnersWithSimpleOWNERSFilePath(self, mock_dirmd_extract): """Checks that OWNERS files are expanded.""" mock_dirmd_extract.return_value = None absolute_path = _MakeOwnersFile('simple_OWNERS', self.temp_dir) src_relative_path = _GetSrcRelativePath(absolute_path) with open(absolute_path, 'w') as owners_file: owners_file.write('\n'.join( ['*****@*****.**', _DEFAULT_COMPONENT, '*****@*****.**'])) histograms = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <owner>{path}</owner> <summary>I like coffee.</summary> </histogram> <histogram name="Maple.Syrup" units="units"> <owner>[email protected]</owner> <owner>{path}</owner> <owner>[email protected]</owner> <summary>I like maple syrup, too.</summary> </histogram> </histograms> """.format(path=src_relative_path)) expected_histograms = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <owner>[email protected]</owner> <owner>[email protected]</owner> <summary>I like coffee.</summary> <component>Default>Component</component> </histogram> <histogram name="Maple.Syrup" units="units"> <owner>[email protected]</owner> <owner>[email protected]</owner> <owner>[email protected]</owner> <owner>[email protected]</owner> <summary>I like maple syrup, too.</summary> <component>Default>Component</component> </histogram> </histograms> """) expand_owners.ExpandHistogramsOWNERS(histograms) self.assertMultiLineEqual(histograms.toxml(), expected_histograms.toxml())
def testExpandOwnersForOWNERSFileWithDuplicateComponents( self, mock_dirmd_extract): """Checks that only one component tag is added if there are duplicates.""" mock_dirmd_extract.return_value = None absolute_path = _MakeOwnersFile('OWNERS', self.temp_dir) src_relative_path = _GetSrcRelativePath(absolute_path) with open(absolute_path, 'w') as owners_file: owners_file.write('\n'.join( ['*****@*****.**', _DEFAULT_COMPONENT])) duplicate_owner_absolute_path = (_MakeOwnersFile( 'duplicate_owner_OWNERS', self.temp_dir)) duplicate_owner_src_relative_path = ( _GetSrcRelativePath(duplicate_owner_absolute_path)) with open(duplicate_owner_absolute_path, 'w') as owners_file: owners_file.write('\n'.join( ['*****@*****.**', _DEFAULT_COMPONENT])) histograms = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <owner>{}</owner> <owner>{}</owner> <summary>I like coffee.</summary> <component>Default>Component</component> </histogram> </histograms> """.format(src_relative_path, duplicate_owner_src_relative_path)) expected_histograms = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <owner>[email protected]</owner> <owner>[email protected]</owner> <summary>I like coffee.</summary> <component>Default>Component</component> </histogram> </histograms> """) expand_owners.ExpandHistogramsOWNERS(histograms) self.assertEqual(histograms.toxml(), expected_histograms.toxml())
def testExpandOwnersWithFileDirectiveOWNERSFilePath( self, mock_dirmd_extract): """Checks that OWNERS files with file directives are expanded.""" mock_dirmd_extract.return_value = None simple_absolute_path = _MakeOwnersFile('simple_OWNERS', self.temp_dir) with open(simple_absolute_path, 'w') as owners_file: owners_file.write('*****@*****.**') file_directive_absolute_path = (_MakeOwnersFile( 'file_directive_OWNERS', self.temp_dir)) file_directive_src_relative_path = ( _GetSrcRelativePath(file_directive_absolute_path)) directive = _GetFileDirective(simple_absolute_path) with open(file_directive_absolute_path, 'w') as owners_file: owners_file.write('\n'.join([ '*****@*****.**', directive, '*****@*****.**', _DEFAULT_COMPONENT ])) histograms = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <owner>{}</owner> <summary>I like coffee.</summary> </histogram> </histograms> """.format(file_directive_src_relative_path)) expected_histograms = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <owner>[email protected]</owner> <owner>[email protected]</owner> <owner>[email protected]</owner> <summary>I like coffee.</summary> <component>Default>Component</component> </histogram> </histograms> """) expand_owners.ExpandHistogramsOWNERS(histograms) self.assertEqual(histograms.toxml(), expected_histograms.toxml())
def MakeNodeWithChildren(doc, tag, children): """Creates a DOM node with specified tag and child nodes. Args: doc: The document to create the node in. tag: The tag to create the node with. children: A list of DOM nodes to add as children. Returns: A DOM node. """ node = doc.createElement(tag) for child in children: if child.tagName == 'histograms': expand_owners.ExpandHistogramsOWNERS(child) node.appendChild(child) return node
def testExpandOwnersWithoutOWNERSFilePath(self): """Checks that histograms without OWNERS file paths are unchanged.""" histograms_without_file_paths = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <summary>I like coffee.</summary> </histogram> </histograms> """) expected_histograms = histograms_without_file_paths expand_owners.ExpandHistogramsOWNERS(histograms_without_file_paths) self.assertEqual(histograms_without_file_paths, expected_histograms)
def testExpandOwnersWithFakeFilePath(self): """Checks that an error is raised with a fake OWNERS file path.""" histograms_with_fake_file_path = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <owner>src/medium/medium/roast/OWNERS</owner> <summary>I like coffee.</summary> </histogram> </histograms> """) with self.assertRaisesRegexp( expand_owners.Error, r'The file at .*medium.*OWNERS does not exist\.'): expand_owners.ExpandHistogramsOWNERS(histograms_with_fake_file_path)
def testExpandOwnersWithLongFilePath(self, mock_dirmd_extract): """Checks that long OWNERS file paths are supported. Most OWNERS file paths appear between owners tags on the same line, e.g. <owner>src/chrome/browser</owner>. However, especially long paths may appear on their own line between the tags. """ mock_dirmd_extract.return_value = None absolute_path = _MakeOwnersFile('simple_OWNERS', self.temp_dir) src_relative_path = _GetSrcRelativePath(absolute_path) with open(absolute_path, 'w') as owners_file: owners_file.write('\n'.join( ['*****@*****.**', _DEFAULT_COMPONENT])) histograms = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <owner> {path} </owner> <summary>I like coffee.</summary> </histogram> </histograms> """.format(path=src_relative_path)) expected_histograms = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <owner>[email protected]</owner> <summary>I like coffee.</summary> <component>Default>Component</component> </histogram> </histograms> """) expand_owners.ExpandHistogramsOWNERS(histograms) self.assertMultiLineEqual(histograms.toxml(), expected_histograms.toxml())
def testExpandOwnersWithoutOWNERSPathPrefix(self): """Checks that an error is raised when the path is not well-formatted.""" histograms_without_src_prefix = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <owner>latte/OWNERS</owner> <summary>I like coffee.</summary> </histogram> </histograms> """) with self.assertRaisesRegexp( expand_owners.Error, r'The given path latte/OWNERS is not well-formatted.*\.'): expand_owners.ExpandHistogramsOWNERS(histograms_without_src_prefix)
def testExpandOwnersWithLongFilePath(self): """ Check that long file path which forces <owner> tags to separate lines is supported. """ absolute_path = _MakeOwnersFile('simple_OWNERS', self.temp_dir) src_relative_path = _GetSrcRelativePath(absolute_path) with open(absolute_path, 'w') as owners_file: owners_file.write('\n'.join( ['*****@*****.**', _DEFAULT_COMPONENT])) histograms = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <owner> {path} </owner> <summary>I like coffee.</summary> </histogram> </histograms> """.format(path=src_relative_path)) expected_histograms = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <owner>[email protected]</owner> <summary>I like coffee.</summary> <component>Default>Component</component> </histogram> </histograms> """) expand_owners.ExpandHistogramsOWNERS(histograms) self.assertMultiLineEqual(histograms.toxml(), expected_histograms.toxml())
def testExpandOwnersWithoutValidPrimaryOwner_InvalidEmail(self): """Checks that an error is raised when the primary owner's email is invalid. A valid primary owner is an individual's email address, e.g. [email protected], [email protected], or the owner placeholder. """ histograms_without_valid_first_owner = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <summary>I like coffee.</summary> </histogram> </histograms> """) with self.assertRaisesRegexp( expand_owners.Error, 'The histogram Caffeination must have a valid primary owner, i.e. a ' 'Googler with an @google.com or @chromium.org email address.'): expand_owners.ExpandHistogramsOWNERS(histograms_without_valid_first_owner)
def testExpandOwnersWithoutValidFirstOwner(self): """Checks that an error is raised when the first owner is not valid. A valid first owner is an individual's email address, e.g. [email protected], or the owner placeholder. """ histograms_without_valid_first_owner = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>src/OWNERS</owner> <summary>I like coffee.</summary> </histogram> </histograms> """) with self.assertRaisesRegexp( expand_owners.Error, 'The histogram Caffeination must have a valid first owner, i.e. an ' 'individual\'s email address.'): expand_owners.ExpandHistogramsOWNERS( histograms_without_valid_first_owner)
def testExpandOwnersWithDuplicateOwners(self): """Checks that owners are unique.""" absolute_path = _MakeOwnersFile('simple_OWNERS', self.temp_dir) src_relative_path = _GetSrcRelativePath(absolute_path) with open(absolute_path, 'w') as owners_file: owners_file.write('\n'.join( ['*****@*****.**', _DEFAULT_COMPONENT, '*****@*****.**'])) histograms = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <owner>{}</owner> <summary>I like coffee.</summary> </histogram> </histograms> """.format(src_relative_path)) expected_histograms = xml.dom.minidom.parseString(""" <histograms> <histogram name="Caffeination" units="mg"> <owner>[email protected]</owner> <owner>[email protected]</owner> <summary>I like coffee.</summary> <component>Default>Component</component> </histogram> </histograms> """) expand_owners.ExpandHistogramsOWNERS(histograms) self.assertMultiLineEqual(histograms.toxml(), expected_histograms.toxml())