aboutsummaryrefslogtreecommitdiff
path: root/llvm_tools
diff options
context:
space:
mode:
authorSalud Lemus <saludlemus@google.com>2019-09-10 10:48:20 -0700
committerSalud Lemus <saludlemus@google.com>2019-09-13 16:11:55 +0000
commitda1c1ef0f4c134839a677398786e8f63b71e036d (patch)
tree67f533894dbb9a3db28c45a5ea20f034cafd80b3 /llvm_tools
parent8340fb901b5ffb6a53c2880a134330c3d0a70361 (diff)
downloadtoolchain-utils-da1c1ef0f4c134839a677398786e8f63b71e036d.tar.gz
LLVM tools: Updated unittests for patch_manager.py
BUG=None TEST='./patch_manager_unittest.py' passes Change-Id: Ib33236b725cf9ffad6cae622aac1ff154db09e0f Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/1796386 Reviewed-by: George Burgess <gbiv@chromium.org> Reviewed-by: Manoj Gupta <manojgupta@chromium.org> Tested-by: Salud Lemus <saludlemus@google.com>
Diffstat (limited to 'llvm_tools')
-rwxr-xr-xllvm_tools/patch_manager_unittest.py735
1 files changed, 421 insertions, 314 deletions
diff --git a/llvm_tools/patch_manager_unittest.py b/llvm_tools/patch_manager_unittest.py
index d32327d7..90200ab8 100755
--- a/llvm_tools/patch_manager_unittest.py
+++ b/llvm_tools/patch_manager_unittest.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2019 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
@@ -9,16 +9,16 @@
from __future__ import print_function
import json
-import mock
import os
-import patch_manager
import subprocess
import unittest
+import unittest.mock as mock
from failure_modes import FailureModes
from test_helpers import CallCountsToMockFunctions
from test_helpers import CreateTemporaryJsonFile
from test_helpers import WritePrettyJsonFile
+import patch_manager
class PatchManagerTest(unittest.TestCase):
@@ -27,14 +27,16 @@ class PatchManagerTest(unittest.TestCase):
# Simulate behavior of 'os.path.isdir()' when the path is not a directory.
@mock.patch.object(os.path, 'isdir', return_value=False)
def testInvalidDirectoryPassedAsCommandLineArgument(self, mock_isdir):
+ test_dir = '/some/path/that/is/not/a/directory'
+
# Verify the exception is raised when the command line argument for
# '--filesdir_path' or '--src_path' is not a directory.
with self.assertRaises(ValueError) as err:
- patch_manager.is_directory('/some/path/that/is/not/a/directory')
+ patch_manager.is_directory(test_dir)
self.assertEqual(
- err.exception.message, 'Path is not a directory: '
- '/some/path/that/is/not/a/directory')
+ str(err.exception), 'Path is not a directory: '
+ '%s' % test_dir)
mock_isdir.assert_called_once()
@@ -42,9 +44,9 @@ class PatchManagerTest(unittest.TestCase):
# passed as the command line argument for '--filesdir_path' or '--src_path'.
@mock.patch.object(os.path, 'isdir', return_value=True)
def testValidDirectoryPassedAsCommandLineArgument(self, mock_isdir):
- self.assertEqual(
- patch_manager.is_directory('/some/path/that/is/a/directory'),
- '/some/path/that/is/a/directory')
+ test_dir = '/some/path/that/is/a/directory'
+
+ self.assertEqual(patch_manager.is_directory(test_dir), test_dir)
mock_isdir.assert_called_once()
@@ -54,14 +56,16 @@ class PatchManagerTest(unittest.TestCase):
def testInvalidPathToPatchMetadataFilePassedAsCommandLineArgument(
self, mock_isfile):
+ abs_path_to_patch_file = '/abs/path/to/PATCHES.json'
+
# Verify the exception is raised when the command line argument for
# '--patch_metadata_file' does not exist or is not a file.
with self.assertRaises(ValueError) as err:
- patch_manager.is_patch_metadata_file('/abs/path/to/PATCHES.json')
+ patch_manager.is_patch_metadata_file(abs_path_to_patch_file)
self.assertEqual(
- err.exception.message, 'Invalid patch metadata file provided: '
- '/abs/path/to/PATCHES.json')
+ str(err.exception), 'Invalid patch metadata file provided: '
+ '%s' % abs_path_to_patch_file)
mock_isfile.assert_called_once()
@@ -69,15 +73,17 @@ class PatchManagerTest(unittest.TestCase):
# metadata file exists and is a file.
@mock.patch.object(os.path, 'isfile', return_value=True)
def testPatchMetadataFileDoesNotEndInJson(self, mock_isfile):
+ abs_path_to_patch_file = '/abs/path/to/PATCHES'
+
# Verify the exception is raises when the command line argument for
# '--patch_metadata_file' exists and is a file but does not end in
# '.json'.
with self.assertRaises(ValueError) as err:
- patch_manager.is_patch_metadata_file('/abs/path/to/PATCHES')
+ patch_manager.is_patch_metadata_file(abs_path_to_patch_file)
self.assertEqual(
- err.exception.message, 'Patch metadata file does not end in \'.json\': '
- '/abs/path/to/PATCHES')
+ str(err.exception), 'Patch metadata file does not end in ".json": '
+ '%s' % abs_path_to_patch_file)
mock_isfile.assert_called_once()
@@ -85,9 +91,11 @@ class PatchManagerTest(unittest.TestCase):
# for '--patch_metadata_file' exists and is a file.
@mock.patch.object(os.path, 'isfile', return_value=True)
def testValidPatchMetadataFilePassedAsCommandLineArgument(self, mock_isfile):
+ abs_path_to_patch_file = '/abs/path/to/PATCHES.json'
+
self.assertEqual(
- patch_manager.is_patch_metadata_file('/abs/path/to/PATCHES.json'),
- '/abs/path/to/PATCHES.json')
+ patch_manager.is_patch_metadata_file(abs_path_to_patch_file),
+ '%s' % abs_path_to_patch_file)
mock_isfile.assert_called_once()
@@ -95,15 +103,18 @@ class PatchManagerTest(unittest.TestCase):
# does not exist.
@mock.patch.object(os.path, 'isdir', return_value=False)
def testInvalidPathToFilesDirWhenConstructingPathToPatch(self, mock_isdir):
+ abs_path_to_filesdir = '/abs/path/to/filesdir'
+
+ rel_patch_path = 'cherry/fixes_stdout.patch'
+
# Verify the exception is raised when the the absolute path to $FILESDIR of
# a package is not a directory.
with self.assertRaises(ValueError) as err:
- patch_manager.GetPathToPatch('/abs/path/to/filesdir',
- 'cherry/fixes_stdout.patch')
+ patch_manager.GetPathToPatch(abs_path_to_filesdir, rel_patch_path)
self.assertEqual(
- err.exception.message, 'Invalid path to $FILESDIR provided: '
- '/abs/path/to/filesdir')
+ str(err.exception), 'Invalid path to $FILESDIR provided: '
+ '%s' % abs_path_to_filesdir)
mock_isdir.assert_called_once()
@@ -114,16 +125,20 @@ class PatchManagerTest(unittest.TestCase):
# patch does not exist.
@mock.patch.object(os.path, 'isfile', return_value=False)
def testConstructedPathToPatchDoesNotExist(self, mock_isfile, mock_isdir):
+ abs_path_to_filesdir = '/abs/path/to/filesdir'
+
+ rel_patch_path = 'cherry/fixes_stdout.patch'
+
+ abs_patch_path = os.path.join(abs_path_to_filesdir, rel_patch_path)
+
# Verify the exception is raised when the absolute path to the patch does
# not exist.
with self.assertRaises(ValueError) as err:
- patch_manager.GetPathToPatch('/abs/path/to/filesdir',
- 'cherry/fixes_stdout.patch')
+ patch_manager.GetPathToPatch(abs_path_to_filesdir, rel_patch_path)
self.assertEqual(
- err.exception.message, 'The absolute path /abs/path/to/filesdir/cherry/'
- 'fixes_stdout.patch to the patch '
- 'cherry/fixes_stdout.patch does not exist')
+ str(err.exception), 'The absolute path %s to the patch %s does not '
+ 'exist' % (abs_patch_path, rel_patch_path))
mock_isdir.assert_called_once()
@@ -136,10 +151,15 @@ class PatchManagerTest(unittest.TestCase):
# patch exists and is a file.
@mock.patch.object(os.path, 'isfile', return_value=True)
def testConstructedPathToPatchSuccessfully(self, mock_isfile, mock_isdir):
+ abs_path_to_filesdir = '/abs/path/to/filesdir'
+
+ rel_patch_path = 'cherry/fixes_stdout.patch'
+
+ abs_patch_path = os.path.join(abs_path_to_filesdir, rel_patch_path)
+
self.assertEqual(
- patch_manager.GetPathToPatch('/abs/path/to/filesdir',
- 'cherry/fixes_stdout.patch'),
- '/abs/path/to/filesdir/cherry/fixes_stdout.patch')
+ patch_manager.GetPathToPatch(abs_path_to_filesdir, rel_patch_path),
+ abs_patch_path)
mock_isdir.assert_called_once()
@@ -149,8 +169,8 @@ class PatchManagerTest(unittest.TestCase):
expected_patch_metadata = 0, None, False
test_patch = {
- "comment": "Redirects output to stdout",
- "rel_patch_path": "cherry/fixes_stdout.patch"
+ 'comment': 'Redirects output to stdout',
+ 'rel_patch_path': 'cherry/fixes_stdout.patch'
}
self.assertEqual(
@@ -160,37 +180,43 @@ class PatchManagerTest(unittest.TestCase):
expected_patch_metadata = 0, 1000, False
test_patch = {
- "comment": "Redirects output to stdout",
- "rel_patch_path": "cherry/fixes_stdout.patch",
- "end_version": 1000
+ 'comment': 'Redirects output to stdout',
+ 'rel_patch_path': 'cherry/fixes_stdout.patch',
+ 'end_version': 1000
}
self.assertEqual(
patch_manager.GetPatchMetadata(test_patch), expected_patch_metadata)
def testFailedToApplyPatchWhenInvalidSrcPathIsPassedIn(self):
+ src_path = '/abs/path/to/src'
+
+ abs_patch_path = '/abs/path/to/filesdir/cherry/fixes_stdout.patch'
+
# Verify the exception is raised when the absolute path to the unpacked
# sources of a package is not a directory.
with self.assertRaises(ValueError) as err:
- patch_manager.ApplyPatch(
- '/abs/path/to/src', '/abs/path/to/filesdir/cherry/fixes_stdout.patch')
+ patch_manager.ApplyPatch(src_path, abs_patch_path)
- self.assertEqual(err.exception.message,
- 'Invalid src path provided: /abs/path/to/src')
+ self.assertEqual(
+ str(err.exception), 'Invalid src path provided: %s' % src_path)
# Simulate behavior of 'os.path.isdir()' when the absolute path to the
# unpacked sources of the package is valid and exists.
@mock.patch.object(os.path, 'isdir', return_value=True)
def testFailedToApplyPatchWhenPatchPathIsInvalid(self, mock_isdir):
+ src_path = '/abs/path/to/src'
+
+ abs_patch_path = '/abs/path/to/filesdir/cherry/fixes_stdout.patch'
+
# Verify the exception is raised when the absolute path to the patch does
# not exist or is not a file.
with self.assertRaises(ValueError) as err:
- patch_manager.ApplyPatch(
- '/abs/path/to/src', '/abs/path/to/filesdir/cherry/fixes_stdout.patch')
+ patch_manager.ApplyPatch(src_path, abs_patch_path)
self.assertEqual(
- err.exception.message, 'Invalid patch file provided: '
- '/abs/path/to/filesdir/cherry/fixes_stdout.patch')
+ str(err.exception), 'Invalid patch file provided: '
+ '%s' % abs_patch_path)
mock_isdir.assert_called_once()
@@ -200,7 +226,7 @@ class PatchManagerTest(unittest.TestCase):
@mock.patch.object(os.path, 'isfile', return_value=True)
# Simulate behavior of 'os.path.isfile()' when the absolute path to the
# patch exists and is a file.
- @mock.patch.object(subprocess, 'check_output')
+ @mock.patch.object(patch_manager, 'check_output')
def testFailedToApplyPatchInDryRun(self, mock_dry_run, mock_isfile,
mock_isdir):
@@ -213,10 +239,11 @@ class PatchManagerTest(unittest.TestCase):
mock_dry_run.side_effect = FailedToApplyPatch
- self.assertEqual(
- patch_manager.ApplyPatch(
- '/abs/path/to/src', '/abs/path/to/filesdir/cherry/'
- 'fixes_stdout.patch'), False)
+ src_path = '/abs/path/to/src'
+
+ abs_patch_path = '/abs/path/to/filesdir/cherry/fixes_stdout.patch'
+
+ self.assertEqual(patch_manager.ApplyPatch(src_path, abs_patch_path), False)
mock_isdir.assert_called_once()
@@ -230,13 +257,13 @@ class PatchManagerTest(unittest.TestCase):
@mock.patch.object(os.path, 'isfile', return_value=True)
# Simulate behavior of 'os.path.isfile()' when the absolute path to the
# patch exists and is a file.
- @mock.patch.object(subprocess, 'check_output')
+ @mock.patch.object(patch_manager, 'check_output')
def testSuccessfullyAppliedPatch(self, mock_dry_run, mock_isfile, mock_isdir):
+ src_path = '/abs/path/to/src'
- self.assertEqual(
- patch_manager.ApplyPatch(
- '/abs/path/to/src', '/abs/path/to/filesdir/cherry/'
- 'fixes_stdout.patch'), True)
+ abs_patch_path = '/abs/path/to/filesdir/cherry/fixes_stdout.patch'
+
+ self.assertEqual(patch_manager.ApplyPatch(src_path, abs_patch_path), True)
mock_isdir.assert_called_once()
@@ -246,32 +273,33 @@ class PatchManagerTest(unittest.TestCase):
def testFailedToUpdatePatchMetadataFileWhenPatchFileNotEndInJson(self):
patch = [{
- "comment": "Redirects output to stdout",
- "rel_patch_path": "cherry/fixes_output.patch",
- "start_version": 10
+ 'comment': 'Redirects output to stdout',
+ 'rel_patch_path': 'cherry/fixes_output.patch',
+ 'start_version': 10
}]
+ abs_patch_path = '/abs/path/to/filesdir/PATCHES'
+
# Verify the exception is raised when the absolute path to the patch
# metadata file does not end in '.json'.
with self.assertRaises(ValueError) as err:
- patch_manager.UpdatePatchMetadataFile('/abs/path/to/filesdir/PATCHES',
- patch)
+ patch_manager.UpdatePatchMetadataFile(abs_patch_path, patch)
self.assertEqual(
- err.exception.message, 'File does not end in \'.json\': '
- '/abs/path/to/filesdir/PATCHES')
+ str(err.exception), 'File does not end in ".json": '
+ '%s' % abs_patch_path)
def testSuccessfullyUpdatedPatchMetadataFile(self):
test_updated_patch_metadata = [{
- "comment": "Redirects output to stdout",
- "rel_patch_path": "cherry/fixes_output.patch",
- "start_version": 10
+ 'comment': 'Redirects output to stdout',
+ 'rel_patch_path': 'cherry/fixes_output.patch',
+ 'start_version': 10
}]
expected_patch_metadata = {
- "comment": "Redirects output to stdout",
- "rel_patch_path": "cherry/fixes_output.patch",
- "start_version": 10
+ 'comment': 'Redirects output to stdout',
+ 'rel_patch_path': 'cherry/fixes_output.patch',
+ 'start_version': 10
}
with CreateTemporaryJsonFile() as json_test_file:
@@ -281,7 +309,7 @@ class PatchManagerTest(unittest.TestCase):
# Make sure the updated patch metadata was written into the temporary
# .json file.
with open(json_test_file) as patch_file:
- patch_contents = patch_manager._ConvertToASCII(json.load(patch_file))
+ patch_contents = json.load(patch_file)
self.assertEqual(len(patch_contents), 1)
@@ -289,19 +317,25 @@ class PatchManagerTest(unittest.TestCase):
@mock.patch.object(patch_manager, 'GetPathToPatch')
def testExceptionThrownWhenHandlingPatches(self, mock_get_path_to_patch):
+ filesdir_path = '/abs/path/to/filesdir'
+
+ abs_patch_path = '/abs/path/to/filesdir/cherry/fixes_output.patch'
+
+ rel_patch_path = 'cherry/fixes_output.patch'
+
# Simulate behavior of 'GetPathToPatch()' when the absolute path to the
# patch does not exist.
def PathToPatchDoesNotExist(filesdir_path, rel_patch_path):
- raise ValueError('The absolute path to /abs/path/to/filesdir/cherry/'
- 'fix_output.patch does not exist')
+ raise ValueError(
+ 'The absolute path to %s does not exist' % abs_patch_path)
# Use the test function to simulate the behavior of 'GetPathToPatch()'.
mock_get_path_to_patch.side_effect = PathToPatchDoesNotExist
test_patch_metadata = [{
- "comment": "Redirects output to stdout",
- "rel_patch_path": "cherry/fixes_output.patch",
- "start_version": 10
+ 'comment': 'Redirects output to stdout',
+ 'rel_patch_path': rel_patch_path,
+ 'start_version': 10
}]
with CreateTemporaryJsonFile() as json_test_file:
@@ -309,20 +343,22 @@ class PatchManagerTest(unittest.TestCase):
with open(json_test_file, 'w') as json_file:
WritePrettyJsonFile(test_patch_metadata, json_file)
+ src_path = '/some/path/to/src'
+
+ revision = 1000
+
# Verify the exception is raised when the absolute path to a patch does
# not exist.
with self.assertRaises(ValueError) as err:
- patch_manager.HandlePatches(1000, json_test_file,
- '/abs/path/to/filesdir',
- '/some/path/to/src', FailureModes.FAIL)
+ patch_manager.HandlePatches(revision, json_test_file, filesdir_path,
+ src_path, FailureModes.FAIL)
self.assertEqual(
- err.exception.message,
- 'The absolute path to /abs/path/to/filesdir/cherry/'
- 'fix_output.patch does not exist')
+ str(err.exception),
+ 'The absolute path to %s does not exist' % abs_patch_path)
- mock_get_path_to_patch.assert_called_once_with('/abs/path/to/filesdir',
- 'cherry/fixes_output.patch')
+ mock_get_path_to_patch.assert_called_once_with(filesdir_path,
+ rel_patch_path)
@mock.patch.object(patch_manager, 'GetPathToPatch')
# Simulate behavior for 'ApplyPatch()' when an applicable patch failed to
@@ -330,15 +366,20 @@ class PatchManagerTest(unittest.TestCase):
@mock.patch.object(patch_manager, 'ApplyPatch', return_value=False)
def testExceptionThrownOnAFailedPatchInFailMode(self, mock_apply_patch,
mock_get_path_to_patch):
+ filesdir_path = '/abs/path/to/filesdir'
+
+ abs_patch_path = '/abs/path/to/filesdir/cherry/fixes_output.patch'
+
+ rel_patch_path = 'cherry/fixes_output.patch'
+
# Simulate behavior for 'GetPathToPatch()' when successfully constructed the
# absolute path to the patch and the patch exists.
- mock_get_path_to_patch.return_value = ('/abs/path/to/filesdir/cherry/'
- 'fixes_output.patch')
+ mock_get_path_to_patch.return_value = abs_patch_path
test_patch_metadata = [{
- "comment": "Redirects output to stdout",
- "rel_patch_path": "cherry/fixes_output.patch",
- "start_version": 1000
+ 'comment': 'Redirects output to stdout',
+ 'rel_patch_path': rel_patch_path,
+ 'start_version': 1000
}]
with CreateTemporaryJsonFile() as json_test_file:
@@ -346,86 +387,91 @@ class PatchManagerTest(unittest.TestCase):
with open(json_test_file, 'w') as json_file:
WritePrettyJsonFile(test_patch_metadata, json_file)
+ src_path = '/some/path/to/src'
+
+ revision = 1000
+
+ patch_name = 'fixes_output.patch'
+
# Verify the exception is raised when the mode is 'fail' and an applicable
# patch fails to apply.
with self.assertRaises(ValueError) as err:
- patch_manager.HandlePatches(1000, json_test_file,
- '/abs/path/to/filesdir',
- '/some/path/to/src', FailureModes.FAIL)
+ patch_manager.HandlePatches(revision, json_test_file, filesdir_path,
+ src_path, FailureModes.FAIL)
- self.assertEqual(err.exception.message,
- 'Failed to apply patch: fixes_output.patch')
+ self.assertEqual(
+ str(err.exception), 'Failed to apply patch: %s' % patch_name)
- mock_get_path_to_patch.assert_called_once_with('/abs/path/to/filesdir',
- 'cherry/fixes_output.patch')
+ mock_get_path_to_patch.assert_called_once_with(filesdir_path,
+ rel_patch_path)
- mock_apply_patch.assert_called_once_with(
- '/some/path/to/src', '/abs/path/to/filesdir/cherry/'
- 'fixes_output.patch')
+ mock_apply_patch.assert_called_once_with(src_path, abs_patch_path)
@mock.patch.object(patch_manager, 'GetPathToPatch')
@mock.patch.object(patch_manager, 'ApplyPatch')
def testSomePatchesFailedToApplyInContinueMode(self, mock_apply_patch,
mock_get_path_to_patch):
- # Simulate behavior for 'GetPathToPatch()' when successfully constructed the
- # absolute path to the patch and the patch exists.
- @CallCountsToMockFunctions
- def MultipleCallsToGetPatchPath(call_count, filesdir_path, rel_patch_path):
- # First patch to call 'GetPathToPatch()'.
- if call_count == 0:
- self.assertEqual(filesdir_path, '/abs/path/to/filesdir')
- self.assertEqual(rel_patch_path, 'cherry/fixes_output.patch')
- return '/abs/path/to/filesdir/cherry/fixes_output.patch'
+ test_patch_1 = {
+ 'comment': 'Redirects output to stdout',
+ 'rel_patch_path': 'cherry/fixes_output.patch',
+ 'start_version': 1000,
+ 'end_version': 1250
+ }
- # Second patch to call 'GetPathToPatch()'.
- if call_count == 1:
- self.assertEqual(filesdir_path, '/abs/path/to/filesdir')
- self.assertEqual(rel_patch_path, 'cherry/fixes_input.patch')
+ test_patch_2 = {
+ 'comment': 'Fixes input',
+ 'rel_patch_path': 'cherry/fixes_input.patch',
+ 'start_version': 1000
+ }
- return '/abs/path/to/filesdir/cherry/fixes_input.patch'
+ test_patch_3 = {
+ 'comment': 'Adds a warning',
+ 'rel_patch_path': 'add_warning.patch',
+ 'start_version': 750,
+ 'end_version': 1500
+ }
- # Third patch to call 'GetPathToPatch()'.
- if call_count == 2:
- self.assertEqual(filesdir_path, '/abs/path/to/filesdir')
- self.assertEqual(rel_patch_path, 'add_warning.patch')
+ test_patch_4 = {
+ 'comment': 'Adds a helper function',
+ 'rel_patch_path': 'add_helper.patch',
+ 'start_version': 20,
+ 'end_version': 900
+ }
- return '/abs/path/to/filesdir/add_warning.patch'
+ test_patch_metadata = [
+ test_patch_1, test_patch_2, test_patch_3, test_patch_4
+ ]
- # Fourth (and last) patch to call 'GetPathToPatch()'.
- if call_count == 3:
- self.assertEqual(filesdir_path, '/abs/path/to/filesdir')
- self.assertEqual(rel_patch_path, 'add_helper.patch')
+ abs_path_to_filesdir = '/abs/path/to/filesdir'
- return '/abs/path/to/filesdir/add_helper.patch'
+ # Simulate behavior for 'GetPathToPatch()' when successfully constructed the
+ # absolute path to the patch and the patch exists.
+ @CallCountsToMockFunctions
+ def MultipleCallsToGetPatchPath(call_count, filesdir_path, rel_patch_path):
+ self.assertEqual(filesdir_path, abs_path_to_filesdir)
+
+ if call_count < 4:
+ self.assertEqual(rel_patch_path,
+ test_patch_metadata[call_count]['rel_patch_path'])
+
+ return os.path.join(abs_path_to_filesdir,
+ test_patch_metadata[call_count]['rel_patch_path'])
- # 'GetPathToPatch()' was called more times than expected (4 times).
assert False, 'Unexpectedly called more than 4 times.'
# Simulate behavior for 'ApplyPatch()' when applying multiple applicable
# patches.
@CallCountsToMockFunctions
def MultipleCallsToApplyPatches(call_count, src_path, path_to_patch):
- # First applicable patch that tries to apply patch.
- if call_count == 0:
- self.assertEqual(path_to_patch,
- '/abs/path/to/filesdir/cherry/fixes_output.patch')
-
- return True
-
- # Second applicable patch that tries to apply patch.
- if call_count == 1:
- self.assertEqual(path_to_patch,
- '/abs/path/to/filesdir/cherry/fixes_input.patch')
-
- return False
+ if call_count < 3:
+ self.assertEqual(
+ path_to_patch,
+ os.path.join(abs_path_to_filesdir,
+ test_patch_metadata[call_count]['rel_patch_path']))
- # Third applicable patch that tries to apply patch.
- if call_count == 2:
- self.assertEqual(path_to_patch,
- '/abs/path/to/filesdir/add_warning.patch')
-
- return False
+ # Simulate that the first patch successfully applied.
+ return call_count == 0
# 'ApplyPatch()' was called more times than expected (3 times).
assert False, 'Unexpectedly called more than 3 times.'
@@ -434,37 +480,6 @@ class PatchManagerTest(unittest.TestCase):
mock_get_path_to_patch.side_effect = MultipleCallsToGetPatchPath
mock_apply_patch.side_effect = MultipleCallsToApplyPatches
- test_patch_1 = {
- "comment": "Redirects output to stdout",
- "rel_patch_path": "cherry/fixes_output.patch",
- "start_version": 1000,
- "end_version": 1250
- }
-
- test_patch_2 = {
- "comment": "Fixes input",
- "rel_patch_path": "cherry/fixes_input.patch",
- "start_version": 1000
- }
-
- test_patch_3 = {
- "comment": "Adds a warning",
- "rel_patch_path": "add_warning.patch",
- "start_version": 750,
- "end_version": 1500
- }
-
- test_patch_4 = {
- "comment": "Adds a helper function",
- "rel_patch_path": "add_helper.patch",
- "start_version": 20,
- "end_version": 900
- }
-
- test_patch_metadata = [
- test_patch_1, test_patch_2, test_patch_3, test_patch_4
- ]
-
expected_applied_patches = ['fixes_output.patch']
expected_failed_patches = ['fixes_input.patch', 'add_warning.patch']
expected_non_applicable_patches = ['add_helper.patch']
@@ -483,9 +498,13 @@ class PatchManagerTest(unittest.TestCase):
with open(json_test_file, 'w') as json_file:
WritePrettyJsonFile(test_patch_metadata, json_file)
- patch_info = patch_manager.HandlePatches(
- 1000, json_test_file, '/abs/path/to/filesdir', '/some/path/to/src',
- FailureModes.CONTINUE)
+ src_path = '/some/path/to/src/'
+
+ revision = 1000
+
+ patch_info = patch_manager.HandlePatches(revision, json_test_file,
+ abs_path_to_filesdir, src_path,
+ FailureModes.CONTINUE)
self.assertDictEqual(patch_info._asdict(), expected_patch_info_dict)
@@ -497,37 +516,52 @@ class PatchManagerTest(unittest.TestCase):
@mock.patch.object(patch_manager, 'ApplyPatch')
def testSomePatchesAreDisabled(self, mock_apply_patch,
mock_get_path_to_patch):
- # Simulate behavior for 'GetPathToPatch()' when successfully constructed the
- # absolute path to the patch and the patch exists.
- @CallCountsToMockFunctions
- def MultipleCallsToGetPatchPath(call_count, filesdir_path, rel_patch_path):
- # First patch to call 'GetPathToPatch()'.
- if call_count == 0:
- self.assertEqual(filesdir_path, '/abs/path/to/filesdir')
- self.assertEqual(rel_patch_path, 'cherry/fixes_output.patch')
- return '/abs/path/to/filesdir/cherry/fixes_output.patch'
+ test_patch_1 = {
+ 'comment': 'Redirects output to stdout',
+ 'rel_patch_path': 'cherry/fixes_output.patch',
+ 'start_version': 1000,
+ 'end_version': 1190
+ }
- # Second patch to call 'GetPathToPatch()'.
- if call_count == 1:
- self.assertEqual(filesdir_path, '/abs/path/to/filesdir')
- self.assertEqual(rel_patch_path, 'cherry/fixes_input.patch')
+ test_patch_2 = {
+ 'comment': 'Fixes input',
+ 'rel_patch_path': 'cherry/fixes_input.patch',
+ 'start_version': 1000
+ }
- return '/abs/path/to/filesdir/cherry/fixes_input.patch'
+ test_patch_3 = {
+ 'comment': 'Adds a warning',
+ 'rel_patch_path': 'add_warning.patch',
+ 'start_version': 750,
+ 'end_version': 1500
+ }
- # Third patch to call 'GetPathToPatch()'.
- if call_count == 2:
- self.assertEqual(filesdir_path, '/abs/path/to/filesdir')
- self.assertEqual(rel_patch_path, 'add_warning.patch')
+ test_patch_4 = {
+ 'comment': 'Adds a helper function',
+ 'rel_patch_path': 'add_helper.patch',
+ 'start_version': 20,
+ 'end_version': 2000
+ }
- return '/abs/path/to/filesdir/add_warning.patch'
+ test_patch_metadata = [
+ test_patch_1, test_patch_2, test_patch_3, test_patch_4
+ ]
+
+ abs_path_to_filesdir = '/abs/path/to/filesdir'
- # Fourth (and last) patch to call 'GetPathToPatch()'.
- if call_count == 3:
- self.assertEqual(filesdir_path, '/abs/path/to/filesdir')
- self.assertEqual(rel_patch_path, 'add_helper.patch')
+ # Simulate behavior for 'GetPathToPatch()' when successfully constructed the
+ # absolute path to the patch and the patch exists.
+ @CallCountsToMockFunctions
+ def MultipleCallsToGetPatchPath(call_count, filesdir_path, rel_patch_path):
+ self.assertEqual(filesdir_path, abs_path_to_filesdir)
- return '/abs/path/to/filesdir/add_helper.patch'
+ if call_count < 4:
+ self.assertEqual(rel_patch_path,
+ test_patch_metadata[call_count]['rel_patch_path'])
+
+ return os.path.join(abs_path_to_filesdir,
+ test_patch_metadata[call_count]['rel_patch_path'])
# 'GetPathToPatch()' was called more times than expected (4 times).
assert False, 'Unexpectedly called more than 4 times.'
@@ -536,26 +570,14 @@ class PatchManagerTest(unittest.TestCase):
# patches.
@CallCountsToMockFunctions
def MultipleCallsToApplyPatches(call_count, src_path, path_to_patch):
- # First applicable patch that tries to apply patch.
- if call_count == 0:
- self.assertEqual(path_to_patch,
- '/abs/path/to/filesdir/cherry/fixes_input.patch')
-
- return False
-
- # Second applicable patch that tries to apply patch.
- if call_count == 1:
- self.assertEqual(path_to_patch,
- '/abs/path/to/filesdir/add_warning.patch')
-
- return True
+ if call_count < 3:
+ self.assertEqual(
+ path_to_patch,
+ os.path.join(abs_path_to_filesdir,
+ test_patch_metadata[call_count + 1]['rel_patch_path']))
- # Third applicable patch that tries to apply patch.
- if call_count == 2:
- self.assertEqual(path_to_patch,
- '/abs/path/to/filesdir/add_helper.patch')
-
- return False
+ # Simulate that the second patch applied successfully.
+ return call_count == 1
# 'ApplyPatch()' was called more times than expected (3 times).
assert False, 'Unexpectedly called more than 3 times.'
@@ -564,37 +586,6 @@ class PatchManagerTest(unittest.TestCase):
mock_get_path_to_patch.side_effect = MultipleCallsToGetPatchPath
mock_apply_patch.side_effect = MultipleCallsToApplyPatches
- test_patch_1 = {
- "comment": "Redirects output to stdout",
- "rel_patch_path": "cherry/fixes_output.patch",
- "start_version": 1000,
- "end_version": 1190
- }
-
- test_patch_2 = {
- "comment": "Fixes input",
- "rel_patch_path": "cherry/fixes_input.patch",
- "start_version": 1000
- }
-
- test_patch_3 = {
- "comment": "Adds a warning",
- "rel_patch_path": "add_warning.patch",
- "start_version": 750,
- "end_version": 1500
- }
-
- test_patch_4 = {
- "comment": "Adds a helper function",
- "rel_patch_path": "add_helper.patch",
- "start_version": 20,
- "end_version": 2000
- }
-
- test_patch_metadata = [
- test_patch_1, test_patch_2, test_patch_3, test_patch_4
- ]
-
expected_applied_patches = ['add_warning.patch']
expected_failed_patches = ['fixes_input.patch', 'add_helper.patch']
expected_disabled_patches = ['fixes_input.patch', 'add_helper.patch']
@@ -622,9 +613,13 @@ class PatchManagerTest(unittest.TestCase):
expected_patch_info_dict['modified_metadata'] = json_test_file
- patch_info = patch_manager.HandlePatches(
- 1200, json_test_file, '/abs/path/to/filesdir', '/some/path/to/src',
- FailureModes.DISABLE_PATCHES)
+ src_path = '/some/path/to/src/'
+
+ revision = 1200
+
+ patch_info = patch_manager.HandlePatches(revision, json_test_file,
+ abs_path_to_filesdir, src_path,
+ FailureModes.DISABLE_PATCHES)
self.assertDictEqual(patch_info._asdict(), expected_patch_info_dict)
@@ -642,13 +637,9 @@ class PatchManagerTest(unittest.TestCase):
# Make sure the updated patch metadata was written into the temporary
# .json file.
with open(json_test_file) as patch_file:
- new_json_file_contents = patch_manager._ConvertToASCII(
- json.load(patch_file))
-
- self.assertEqual(len(new_json_file_contents), 4)
+ new_json_file_contents = json.load(patch_file)
- for i in range(4):
- self.assertDictEqual(new_json_file_contents[i], expected_json_file[i])
+ self.assertListEqual(new_json_file_contents, expected_json_file)
self.assertEqual(mock_get_path_to_patch.call_count, 4)
@@ -657,52 +648,146 @@ class PatchManagerTest(unittest.TestCase):
@mock.patch.object(patch_manager, 'GetPathToPatch')
@mock.patch.object(patch_manager, 'ApplyPatch')
def testSomePatchesAreRemoved(self, mock_apply_patch, mock_get_path_to_patch):
+ # For the 'remove_patches' mode, this patch is expected to be in the
+ # 'non_applicable_patches' list and 'removed_patches' list because
+ # the 'svn_version' (1500) >= 'end_version' (1190).
+ test_patch_1 = {
+ 'comment': 'Redirects output to stdout',
+ 'rel_patch_path': 'cherry/fixes_output.patch',
+ 'start_version': 1000,
+ 'end_version': 1190
+ }
+
+ # For the 'remove_patches' mode, this patch is expected to be in the
+ # 'applicable_patches' list (which is the list that the .json file will be
+ # updated with) because the 'svn_version' < 'inf' (this patch does not have
+ # an 'end_version' value which implies 'end_version' == 'inf').
+ test_patch_2 = {
+ 'comment': 'Fixes input',
+ 'rel_patch_path': 'cherry/fixes_input.patch',
+ 'start_version': 1000
+ }
+
+ # For the 'remove_patches' mode, this patch is expected to be in the
+ # 'non_applicable_patches' list and 'removed_patches' list because
+ # the 'svn_version' (1500) >= 'end_version' (1500).
+ test_patch_3 = {
+ 'comment': 'Adds a warning',
+ 'rel_patch_path': 'add_warning.patch',
+ 'start_version': 750,
+ 'end_version': 1500
+ }
+
+ # For the 'remove_patches' mode, this patch is expected to be in the
+ # 'non_applicable_patches' list and 'removed_patches' list because
+ # the 'svn_version' (1500) >= 'end_version' (1400).
+ test_patch_4 = {
+ 'comment': 'Adds a helper function',
+ 'rel_patch_path': 'add_helper.patch',
+ 'start_version': 20,
+ 'end_version': 1400
+ }
+
+ test_patch_metadata = [
+ test_patch_1, test_patch_2, test_patch_3, test_patch_4
+ ]
+
+ abs_path_to_filesdir = '/abs/path/to/filesdir'
+
# Simulate behavior for 'GetPathToPatch()' when successfully constructed the
# absolute path to the patch and the patch exists.
@CallCountsToMockFunctions
def MultipleCallsToGetPatchPath(call_count, filesdir_path, rel_patch_path):
- # First patch to call 'GetPathToPatch()'.
- if call_count == 0:
- self.assertEqual(filesdir_path, '/abs/path/to/filesdir')
- self.assertEqual(rel_patch_path, 'cherry/fixes_output.patch')
+ self.assertEqual(filesdir_path, abs_path_to_filesdir)
- return '/abs/path/to/filesdir/cherry/fixes_output.patch'
+ if call_count < 4:
+ self.assertEqual(rel_patch_path,
+ test_patch_metadata[call_count]['rel_patch_path'])
- # Second patch to call 'GetPathToPatch()'.
- if call_count == 1:
- self.assertEqual(filesdir_path, '/abs/path/to/filesdir')
- self.assertEqual(rel_patch_path, 'cherry/fixes_input.patch')
+ return os.path.join(abs_path_to_filesdir,
+ test_patch_metadata[call_count]['rel_patch_path'])
- return '/abs/path/to/filesdir/cherry/fixes_input.patch'
+ assert False, 'Unexpectedly called more than 4 times.'
- # Third patch to call 'GetPathToPatch()'.
- if call_count == 2:
- self.assertEqual(filesdir_path, '/abs/path/to/filesdir')
- self.assertEqual(rel_patch_path, 'add_warning.patch')
+ # Use the test function to simulate behavior of 'GetPathToPatch()'.
+ mock_get_path_to_patch.side_effect = MultipleCallsToGetPatchPath
- return '/abs/path/to/filesdir/add_warning.patch'
+ expected_applied_patches = []
+ expected_failed_patches = []
+ expected_disabled_patches = []
+ expected_non_applicable_patches = [
+ 'fixes_output.patch', 'add_warning.patch', 'add_helper.patch'
+ ]
+ expected_removed_patches = [
+ '/abs/path/to/filesdir/cherry/fixes_output.patch',
+ '/abs/path/to/filesdir/add_warning.patch',
+ '/abs/path/to/filesdir/add_helper.patch'
+ ]
- # Fourth (and last) patch to call 'GetPathToPatch()'.
- if call_count == 3:
- self.assertEqual(filesdir_path, '/abs/path/to/filesdir')
- self.assertEqual(rel_patch_path, 'add_helper.patch')
+ # Assigned 'None' for now, but it is expected that the patch metadata file
+ # will be modified, so the 'expected_patch_info_dict's' value for the
+ # key 'modified_metadata' will get updated to the temporary .json file once
+ # the file is created.
+ expected_modified_metadata_file = None
- return '/abs/path/to/filesdir/add_helper.patch'
+ expected_patch_info_dict = {
+ 'applied_patches': expected_applied_patches,
+ 'failed_patches': expected_failed_patches,
+ 'non_applicable_patches': expected_non_applicable_patches,
+ 'disabled_patches': expected_disabled_patches,
+ 'removed_patches': expected_removed_patches,
+ 'modified_metadata': expected_modified_metadata_file
+ }
- # 'GetPathToPatch()' was called more times than expected (4 times).
- assert False, 'Unexpectedly called more than 4 times.'
+ with CreateTemporaryJsonFile() as json_test_file:
+ # Write the test patch metadata to the temporary .json file.
+ with open(json_test_file, 'w') as json_file:
+ WritePrettyJsonFile(test_patch_metadata, json_file)
- # Use the test function to simulate behavior of 'GetPathToPatch()'.
- mock_get_path_to_patch.side_effect = MultipleCallsToGetPatchPath
+ expected_patch_info_dict['modified_metadata'] = json_test_file
+
+ abs_path_to_filesdir = '/abs/path/to/filesdir'
+
+ src_path = '/some/path/to/src/'
+
+ revision = 1500
+
+ patch_info = patch_manager.HandlePatches(revision, json_test_file,
+ abs_path_to_filesdir, src_path,
+ FailureModes.REMOVE_PATCHES)
+
+ self.assertDictEqual(patch_info._asdict(), expected_patch_info_dict)
+
+ # 'test_patch_2' was an applicable patch, so this patch will be the only
+ # patch that is in temporary .json file. The other patches were not
+ # applicable (they failed the applicable check), so they will not be in
+ # the .json file.
+ expected_json_file = [test_patch_2]
+
+ # Make sure the updated patch metadata was written into the temporary
+ # .json file.
+ with open(json_test_file) as patch_file:
+ new_json_file_contents = json.load(patch_file)
+
+ self.assertListEqual(new_json_file_contents, expected_json_file)
+
+ self.assertEqual(mock_get_path_to_patch.call_count, 4)
+
+ mock_apply_patch.assert_not_called()
+
+ @mock.patch.object(patch_manager, 'GetPathToPatch')
+ @mock.patch.object(patch_manager, 'ApplyPatch')
+ def testSuccessfullyDidNotRemoveAFuturePatch(self, mock_apply_patch,
+ mock_get_path_to_patch):
# For the 'remove_patches' mode, this patch is expected to be in the
# 'non_applicable_patches' list and 'removed_patches' list because
- # the 'svn_version' (1500) >= 'end_version' (1190).
+ # the 'svn_version' (1200) >= 'end_version' (1190).
test_patch_1 = {
- "comment": "Redirects output to stdout",
- "rel_patch_path": "cherry/fixes_output.patch",
- "start_version": 1000,
- "end_version": 1190
+ 'comment': 'Redirects output to stdout',
+ 'rel_patch_path': 'cherry/fixes_output.patch',
+ 'start_version': 1000,
+ 'end_version': 1190
}
# For the 'remove_patches' mode, this patch is expected to be in the
@@ -710,45 +795,66 @@ class PatchManagerTest(unittest.TestCase):
# updated with) because the 'svn_version' < 'inf' (this patch does not have
# an 'end_version' value which implies 'end_version' == 'inf').
test_patch_2 = {
- "comment": "Fixes input",
- "rel_patch_path": "cherry/fixes_input.patch",
- "start_version": 1000
+ 'comment': 'Fixes input',
+ 'rel_patch_path': 'cherry/fixes_input.patch',
+ 'start_version': 1000
}
# For the 'remove_patches' mode, this patch is expected to be in the
- # 'non_applicable_patches' list and 'removed_patches' list because
- # the 'svn_version' (1500) >= 'end_version' (1500).
+ # 'applicable_patches' list because 'svn_version' >= 'start_version' and
+ # 'svn_version' < 'end_version'.
test_patch_3 = {
- "comment": "Adds a warning",
- "rel_patch_path": "add_warning.patch",
- "start_version": 750,
- "end_version": 1500
+ 'comment': 'Adds a warning',
+ 'rel_patch_path': 'add_warning.patch',
+ 'start_version': 750,
+ 'end_version': 1500
}
# For the 'remove_patches' mode, this patch is expected to be in the
- # 'non_applicable_patches' list and 'removed_patches' list because
- # the 'svn_version' (1500) >= 'end_version' (1400).
+ # 'applicable_patches' list because the patch is from the future (e.g.
+ # 'start_version' > 'svn_version' (1200), so it should NOT be removed.
test_patch_4 = {
- "comment": "Adds a helper function",
- "rel_patch_path": "add_helper.patch",
- "start_version": 20,
- "end_version": 1400
+ 'comment': 'Adds a helper function',
+ 'rel_patch_path': 'add_helper.patch',
+ 'start_version': 1600,
+ 'end_version': 2000
}
test_patch_metadata = [
test_patch_1, test_patch_2, test_patch_3, test_patch_4
]
+ abs_path_to_filesdir = '/abs/path/to/filesdir'
+
+ # Simulate behavior for 'GetPathToPatch()' when successfully constructed the
+ # absolute path to the patch and the patch exists.
+ @CallCountsToMockFunctions
+ def MultipleCallsToGetPatchPath(call_count, filesdir_path, rel_patch_path):
+ self.assertEqual(filesdir_path, abs_path_to_filesdir)
+
+ if call_count < 4:
+ self.assertEqual(rel_patch_path,
+ test_patch_metadata[call_count]['rel_patch_path'])
+
+ return os.path.join(abs_path_to_filesdir,
+ test_patch_metadata[call_count]['rel_patch_path'])
+
+ # 'GetPathToPatch()' was called more times than expected (4 times).
+ assert False, 'Unexpectedly called more than 4 times.'
+
+ # Use the test function to simulate behavior of 'GetPathToPatch()'.
+ mock_get_path_to_patch.side_effect = MultipleCallsToGetPatchPath
+
expected_applied_patches = []
expected_failed_patches = []
expected_disabled_patches = []
- expected_non_applicable_patches = [
- 'fixes_output.patch', 'add_warning.patch', 'add_helper.patch'
- ]
+
+ # 'add_helper.patch' is still a 'non applicable' patch meaning it does not
+ # apply in revision 1200 but it will NOT be removed because it is a future
+ # patch.
+ expected_non_applicable_patches = ['fixes_output.patch', 'add_helper.patch']
expected_removed_patches = [
- '/abs/path/to/filesdir/cherry/fixes_output.patch',
- '/abs/path/to/filesdir/add_warning.patch',
- '/abs/path/to/filesdir/add_helper.patch'
+ '/abs/path/to/filesdir/cherry/fixes_output.patch'
]
# Assigned 'None' for now, but it is expected that the patch metadata file
@@ -773,9 +879,13 @@ class PatchManagerTest(unittest.TestCase):
expected_patch_info_dict['modified_metadata'] = json_test_file
- patch_info = patch_manager.HandlePatches(
- 1500, json_test_file, '/abs/path/to/filesdir', '/some/path/to/src',
- FailureModes.REMOVE_PATCHES)
+ src_path = '/some/path/to/src/'
+
+ revision = 1200
+
+ patch_info = patch_manager.HandlePatches(revision, json_test_file,
+ abs_path_to_filesdir, src_path,
+ FailureModes.REMOVE_PATCHES)
self.assertDictEqual(patch_info._asdict(), expected_patch_info_dict)
@@ -783,17 +893,14 @@ class PatchManagerTest(unittest.TestCase):
# patch that is in temporary .json file. The other patches were not
# applicable (they failed the applicable check), so they will not be in
# the .json file.
- expected_json_file = [test_patch_2]
+ expected_json_file = [test_patch_2, test_patch_3, test_patch_4]
# Make sure the updated patch metadata was written into the temporary
# .json file.
with open(json_test_file) as patch_file:
- new_json_file_contents = patch_manager._ConvertToASCII(
- json.load(patch_file))
-
- self.assertEqual(len(new_json_file_contents), 1)
+ new_json_file_contents = json.load(patch_file)
- self.assertDictEqual(new_json_file_contents[0], expected_json_file[0])
+ self.assertListEqual(new_json_file_contents, expected_json_file)
self.assertEqual(mock_get_path_to_patch.call_count, 4)