Files
munki/tests/code/client/munkilib/appleupdates_test.py

1759 lines
74 KiB
Python
Executable File

#!/usr/bin/python
# encoding: utf-8
"""
appleupdates_test.py
Unit tests for appleupdates.
"""
# Copyright 2011 Google.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import appleupdates
try:
import mox
except ImportError:
import sys
print >>sys.stderr, "mox module is required. run: easy_install mox"
raise
from Foundation import NSDate
import os
import unittest
import stubout
class TestAppleUpdates(mox.MoxTestBase):
"""Test AppleUpdates class."""
def setUp(self):
mox.MoxTestBase.setUp(self)
self.stubs = stubout.StubOutForTesting()
self.au = appleupdates.AppleUpdates()
self.encoded_cache_dir = appleupdates.urllib2.quote(self.au.cache_dir)
def tearDown(self):
self.mox.UnsetStubs()
self.stubs.UnsetAll()
def _MockMunkiDisplay(self):
"""Mock out all munkicommon.display_* methods."""
for display in [
'percent_done', 'status_major', 'status_minor',
'info', 'detail', 'debug1', 'debug2', 'warning', 'error']:
self.mox.StubOutWithMock(
appleupdates.munkicommon, 'display_%s' % display)
def _MockMunkiStatus(self):
"""Mock out munkistatus.message/detail/percent methods."""
for method in ['message', 'detail', 'percent']:
self.mox.StubOutWithMock(appleupdates.munkistatus, method)
def _MockFoundationPlist(self):
"""Mock out all FoundationPlist functions."""
for func_name in [
'readPlist', 'readPlistFromString', 'writePlist',
'writePlistToString']:
self.mox.StubOutWithMock(appleupdates.FoundationPlist, func_name)
def _MockUpdateCheck(self):
"""Mock out all updatecheck functions."""
for func_name in [
'getPrimaryManifestCatalogs', 'getItemDetail']:
self.mox.StubOutWithMock(appleupdates.updatecheck, func_name)
def testResetMunkiStatusAndDisplayMessageMunkiStatusOutputTrue(self):
"""Tests _ResetMunkiStatusAndDisplayMessage(), GUI is present."""
self._MockMunkiStatus()
self._MockMunkiDisplay()
self.mox.StubOutWithMock(appleupdates.munkicommon, 'log')
msg = 'foo + bar == foobar'
appleupdates.munkicommon.munkistatusoutput = True
appleupdates.munkicommon.display_status_major(msg)
self.mox.ReplayAll()
self.au._ResetMunkiStatusAndDisplayMessage(msg)
self.mox.VerifyAll()
def testResetMunkiStatusAndDisplayMessageMunkiStatusOutputFalse(self):
"""Tests _ResetMunkiStatusAndDisplayMessage(), GUI not present."""
self._MockMunkiDisplay()
msg = 'asdf'
appleupdates.munkicommon.munkistatusoutput = False
appleupdates.munkicommon.display_status_major(msg)
self.mox.ReplayAll()
self.au._ResetMunkiStatusAndDisplayMessage(msg)
self.mox.VerifyAll()
def testGetURLPath(self):
"""Tests _GetURLPath()."""
path = '/foo/bar/index.html'
url = 'https://www.example.com' + path
output_path = self.au._GetURLPath(url)
self.assertEqual(output_path, path)
path = '/foo/bar/'
url = 'https://www.example.com' + path
output_path = self.au._GetURLPath(url)
self.assertEqual(output_path, path)
def testRewriteURL(self):
"""Tests RewriteURL()."""
self.mox.StubOutWithMock(self.au, '_GetURLPath')
managed_installs = appleupdates.urllib2.quote(self.au.cache_dir)
path = '/foo/bar/'
url = 'https://www.example.com' + path
self.au._GetURLPath(url).AndReturn(path)
expected_output_url = 'file://localhost' + self.encoded_cache_dir + path
self.mox.ReplayAll()
output_url = self.au.RewriteURL(url)
self.assertEqual(output_url, expected_output_url)
self.mox.VerifyAll()
def testRewriteURLWithFileURL(self):
"""Tests RewriteURL() with a file://localhost/Managed*... URL."""
url = 'file://localhost' + self.encoded_cache_dir + 'foo/bar'
self.mox.ReplayAll()
output_url = self.au.RewriteURL(url)
self.assertEqual(output_url, url)
self.mox.VerifyAll()
def testRewriteProductURLs(self):
"""Test RewriteProductURLs()."""
self.mox.StubOutWithMock(self.au, 'RewriteURL')
product = {
'ServerMetadataURL': 'urlin0',
'Packages': [
{
'URL': 'urlin1',
'MetadataURL': 'urlin2',
},
],
'Distributions': {'lang': 'urlin3'},
}
self.au.RewriteURL('urlin0').AndReturn('urlout0')
self.au.RewriteURL('urlin2').AndReturn('urlout2')
self.au.RewriteURL('urlin3').AndReturn('urlout3')
self.mox.ReplayAll()
self.au.RewriteProductURLs(product)
self.assertEqual(product['ServerMetadataURL'], 'urlout0')
self.assertEqual(product['Packages'][0]['MetadataURL'], 'urlout2')
self.assertEqual(product['Distributions']['lang'], 'urlout3')
self.mox.VerifyAll()
def testRewriteProductURLsWhenNoServerMetadataURL(self):
"""Test RewriteProductURLs() when no ServerMetadataURL in product."""
self.mox.StubOutWithMock(self.au, 'RewriteURL')
product = {
'Packages': [
{
'URL': 'urlin1',
'MetadataURL': 'urlin2',
},
],
'Distributions': {'lang': 'urlin3'},
}
self.au.RewriteURL('urlin2').AndReturn('urlout2')
self.au.RewriteURL('urlin3').AndReturn('urlout3')
self.mox.ReplayAll()
self.au.RewriteProductURLs(product)
self.assertFalse('ServerMetadataURL' in product)
self.assertEqual(product['Packages'][0]['MetadataURL'], 'urlout2')
self.assertEqual(product['Distributions']['lang'], 'urlout3')
self.mox.VerifyAll()
def testRewriteProductURLsWhenRewritePkgUrls(self):
"""Test RewriteProductURLs() when rewrite_pkg_urls=True."""
self.mox.StubOutWithMock(self.au, 'RewriteURL')
product = {
'ServerMetadataURL': 'urlin0',
'Packages': [
{
'URL': 'urlin1',
'MetadataURL': 'urlin2',
},
],
'Distributions': {'lang': 'urlin3'},
}
self.au.RewriteURL('urlin0').AndReturn('urlout0')
self.au.RewriteURL('urlin1').AndReturn('urlout1')
self.au.RewriteURL('urlin2').AndReturn('urlout2')
self.au.RewriteURL('urlin3').AndReturn('urlout3')
self.mox.ReplayAll()
self.au.RewriteProductURLs(product, rewrite_pkg_urls=True)
self.assertEqual(product['ServerMetadataURL'], 'urlout0')
self.assertEqual(product['Packages'][0]['URL'], 'urlout1')
self.assertEqual(product['Packages'][0]['MetadataURL'], 'urlout2')
self.assertEqual(product['Distributions']['lang'], 'urlout3')
self.mox.VerifyAll()
def testRewriteCatalogURLs(self):
"""Test RewriteCatalogURLs()."""
self.mox.StubOutWithMock(self.au, 'RewriteProductURLs')
catalog = {
'Products': {
'key0': 'data',
},
}
self.au.RewriteProductURLs(
catalog['Products']['key0'], rewrite_pkg_urls=1).AndReturn(None)
self.mox.ReplayAll()
self.au.RewriteCatalogURLs(catalog, rewrite_pkg_urls=1)
self.mox.VerifyAll()
def testRewriteCatalogURLsWhenNoProducts(self):
"""Test RewriteCatalogURLs() when no products in catalog."""
self.mox.StubOutWithMock(self.au, 'RewriteProductURLs')
catalog = {
'not Products': {
'key0': 'data',
},
}
self.mox.ReplayAll()
self.au.RewriteCatalogURLs(catalog)
self.mox.VerifyAll()
def testCacheUpdateMetadata(self):
"""Test CacheUpdateMetadata()."""
self._MockMunkiDisplay()
self._MockFoundationPlist()
self.mox.StubOutWithMock(self.au, 'RetrieveURLToCacheDir')
self.mox.StubOutWithMock(self.au, 'RewriteCatalogURLs')
self.mox.StubOutWithMock(appleupdates.os.path, 'exists')
self.mox.StubOutWithMock(appleupdates.os, 'makedirs')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'stopRequested')
catalog = {
'Products': {
'key0': {
'ServerMetadataURL': 'url0',
'Packages': [
{'MetadataURL': 'url1'},
],
'Distributions': {
'lang': 'url2',
},
},
},
}
appleupdates.FoundationPlist.readPlist(
self.au.filtered_catalog_path).AndReturn(catalog)
appleupdates.munkicommon.stopRequested().AndReturn(False)
appleupdates.munkicommon.display_status_minor(
'Caching metadata for product ID %s', 'key0')
self.au.RetrieveURLToCacheDir(
'url0', copy_only_if_missing=True).AndReturn(None)
appleupdates.munkicommon.stopRequested().AndReturn(False)
appleupdates.munkicommon.display_status_minor(
'Caching package metadata for product ID %s', 'key0')
self.au.RetrieveURLToCacheDir(
'url1', copy_only_if_missing=True).AndReturn(None)
appleupdates.munkicommon.stopRequested().AndReturn(False)
appleupdates.munkicommon.display_status_minor(
'Caching %s distribution for product ID %s', 'lang',
'key0').AndReturn(None)
self.au.RetrieveURLToCacheDir(
'url2', copy_only_if_missing=True).AndReturn(None)
appleupdates.munkicommon.stopRequested().AndReturn(False)
self.au.RewriteCatalogURLs(
catalog, rewrite_pkg_urls=False).AndReturn(None)
appleupdates.os.path.exists(
self.au.local_catalog_dir).AndReturn(False)
appleupdates.os.makedirs(self.au.local_catalog_dir).AndReturn(None)
appleupdates.FoundationPlist.writePlist(
catalog, self.au.local_download_catalog_path)
self.au.RewriteCatalogURLs(catalog, rewrite_pkg_urls=True).AndReturn(
None)
appleupdates.FoundationPlist.writePlist(
catalog, self.au.local_catalog_path)
self.mox.ReplayAll()
self.assertEqual(None, self.au.CacheUpdateMetadata())
self.mox.VerifyAll()
def testCacheUpdateMetadataWhenMakedirsError(self):
"""Test CacheUpdateMetadata() when os.makedirs() errors."""
self._MockMunkiDisplay()
self._MockFoundationPlist()
self.mox.StubOutWithMock(self.au, 'RetrieveURLToCacheDir')
self.mox.StubOutWithMock(appleupdates.os.path, 'exists')
self.mox.StubOutWithMock(appleupdates.os, 'makedirs')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'stopRequested')
catalog = {
'Products': {
'key0': {
'ServerMetadataURL': 'url0',
'Packages': [
{'MetadataURL': 'url1'},
],
'Distributions': {
'lang': 'url2',
},
},
},
}
appleupdates.FoundationPlist.readPlist(
self.au.filtered_catalog_path).AndReturn(catalog)
appleupdates.munkicommon.stopRequested().AndReturn(False)
appleupdates.munkicommon.display_status_minor(
'Caching metadata for product ID %s', 'key0')
self.au.RetrieveURLToCacheDir(
'url0', copy_only_if_missing=True).AndReturn(None)
appleupdates.munkicommon.stopRequested().AndReturn(False)
appleupdates.munkicommon.display_status_minor(
'Caching package metadata for product ID %s', 'key0')
self.au.RetrieveURLToCacheDir(
'url1', copy_only_if_missing=True).AndReturn(None)
appleupdates.munkicommon.stopRequested().AndReturn(False)
appleupdates.munkicommon.display_status_minor(
'Caching %s distribution for product ID %s', 'lang',
'key0').AndReturn(None)
self.au.RetrieveURLToCacheDir(
'url2', copy_only_if_missing=True).AndReturn(None)
appleupdates.munkicommon.stopRequested().AndReturn(False)
appleupdates.os.path.exists(
self.au.local_catalog_dir).AndReturn(False)
appleupdates.os.makedirs(self.au.local_catalog_dir).AndRaise(OSError)
self.mox.ReplayAll()
self.assertRaises(
appleupdates.ReplicationError, self.au.CacheUpdateMetadata)
self.mox.VerifyAll()
def testCacheUpdateMetadataWhenNoProducts(self):
"""Test CacheUpdateMetadata() when no products in catalog."""
self._MockMunkiDisplay()
self._MockFoundationPlist()
catalog = {}
appleupdates.FoundationPlist.readPlist(
self.au.filtered_catalog_path).AndReturn(catalog)
self.mox.ReplayAll()
self.assertEqual(None, self.au.CacheUpdateMetadata())
self.mox.VerifyAll()
def testRetrieveURLToCacheDir(self):
"""Tests RetrieveURLToCacheDir()."""
self.mox.StubOutWithMock(self.au, '_GetURLPath')
self.mox.StubOutWithMock(appleupdates.os, 'makedirs')
self.mox.StubOutWithMock(appleupdates.os.path, 'exists')
self.mox.StubOutWithMock(self.au, 'GetSoftwareUpdateResource')
path = '/foo/bar'
url = 'https://www.example.com' + path
local_file_path = os.path.join(self.au.cache_dir, path.lstrip('/'))
local_dir_path = os.path.dirname(local_file_path)
self.au._GetURLPath(url).AndReturn(path)
appleupdates.os.path.exists(local_dir_path).AndReturn(False)
appleupdates.os.makedirs(local_dir_path).AndReturn(None)
self.au.GetSoftwareUpdateResource(
url, local_file_path, resume=True).AndReturn(None)
self.mox.ReplayAll()
output = self.au.RetrieveURLToCacheDir(url)
self.assertEqual(output, local_file_path)
self.mox.VerifyAll()
def testRetrieveURLToCacheDirWithMunkiDownloadError(self):
"""Tests RetrieveURLToCacheDir() with MunkiDownloadError."""
self.mox.StubOutWithMock(self.au, '_GetURLPath')
self.mox.StubOutWithMock(appleupdates.os, 'makedirs')
self.mox.StubOutWithMock(appleupdates.os.path, 'exists')
self.mox.StubOutWithMock(self.au, 'GetSoftwareUpdateResource')
path = '/foo/bar'
url = 'https://www.example.com' + path
local_file_path = os.path.join(self.au.cache_dir, path.lstrip('/'))
local_dir_path = os.path.dirname(local_file_path)
self.au._GetURLPath(url).AndReturn(path)
appleupdates.os.path.exists(local_dir_path).AndReturn(False)
appleupdates.os.makedirs(local_dir_path).AndReturn(None)
self.au.GetSoftwareUpdateResource(
url, local_file_path, resume=True).AndRaise(
appleupdates.fetch.MunkiDownloadError)
self.mox.ReplayAll()
self.assertRaises(
appleupdates.Error, self.au.RetrieveURLToCacheDir, url)
self.mox.VerifyAll()
def testRetrieveURLToCacheDirMakedirsError(self):
"""Tests RetrieveURLToCacheDir() with os.makedirs() error."""
self.mox.StubOutWithMock(self.au, '_GetURLPath')
self.mox.StubOutWithMock(appleupdates.os, 'makedirs')
self.mox.StubOutWithMock(appleupdates.os.path, 'exists')
path = '/foo/bar'
url = 'https://www.example.com' + path
local_file_path = os.path.join(self.au.cache_dir, path.lstrip('/'))
local_dir_path = os.path.dirname(local_file_path)
self.au._GetURLPath(url).AndReturn(path)
appleupdates.os.path.exists(local_dir_path).AndReturn(False)
appleupdates.os.makedirs(local_dir_path).AndRaise(OSError)
self.mox.ReplayAll()
self.assertRaises(
appleupdates.Error, self.au.RetrieveURLToCacheDir, url)
self.mox.VerifyAll()
def testRetrieveURLToCacheDirCopyOnlyIfMissing(self):
"""Tests RetrieveURLToCacheDir() with copy_only_if_missing=True."""
self.mox.StubOutWithMock(self.au, '_GetURLPath')
self.mox.StubOutWithMock(appleupdates.os.path, 'exists')
path = '/foo/bar'
url = 'https://www.example.com' + path
local_file_path = os.path.join(self.au.cache_dir, path.lstrip('/'))
self.au._GetURLPath(url).AndReturn(path)
appleupdates.os.path.exists(local_file_path).AndReturn(True)
self.mox.ReplayAll()
output = self.au.RetrieveURLToCacheDir(url, copy_only_if_missing=True)
self.assertEqual(output, local_file_path)
self.mox.VerifyAll()
def testWriteFilteredCatalog(self):
"""Tests _WriteFilteredCatalog()."""
self._MockFoundationPlist()
catalog_path = 'foo/catalog.sucatalog'
product_ids = ['1', '3']
catalog = {'Products': {'1': 'foo', '2': 'bar', '3': None}}
# output catalog will be missing 2, since it's not in product_ids
output_catalog = {'Products': {'1': 'foo', '3': None}}
appleupdates.FoundationPlist.readPlist(
self.au.extracted_catalog_path).AndReturn(catalog)
appleupdates.FoundationPlist.writePlist(
output_catalog, catalog_path).AndReturn(None)
self.mox.ReplayAll()
self.au._WriteFilteredCatalog(product_ids, catalog_path)
self.mox.VerifyAll()
def testIsRestartNeededFalse(self):
"""Tests IsRestartNeeded() when restart is not needed."""
self._MockFoundationPlist()
apple_updates = {
'AppleUpdates': [
{'RestartAction': 'None'},
{'RestartAction': 'Nope'},
]
}
appleupdates.FoundationPlist.readPlist(
self.au.apple_updates_plist).AndReturn(apple_updates)
self.mox.ReplayAll()
self.assertFalse(self.au.IsRestartNeeded())
self.mox.VerifyAll()
def testIsRestartNeededTrue(self):
"""Tests IsRestartNeeded() when restart is needed."""
self._MockFoundationPlist()
apple_updates = {
'AppleUpdates': [
{'RestartAction': 'None'},
{'RestartAction': self.au.RESTART_ACTIONS[0]},
]
}
appleupdates.FoundationPlist.readPlist(
self.au.apple_updates_plist).AndReturn(apple_updates)
self.mox.ReplayAll()
self.assertTrue(self.au.IsRestartNeeded())
self.mox.VerifyAll()
def testIsRestartNeededFoundationPlistError(self):
"""Tests IsRestartNeeded() when FoundationPlist has a read error."""
self._MockFoundationPlist()
exc = appleupdates.FoundationPlist.NSPropertyListSerializationException
appleupdates.FoundationPlist.readPlist(
self.au.apple_updates_plist).AndRaise(exc)
self.mox.ReplayAll()
self.assertTrue(self.au.IsRestartNeeded())
self.mox.VerifyAll()
def testClearAppleUpdateInfo(self):
"""Tests ClearAppleUpdateInfo()."""
self.mox.StubOutWithMock(appleupdates.os, 'unlink')
appleupdates.os.unlink(self.au.apple_updates_plist).AndReturn(None)
appleupdates.os.unlink(self.au.applicable_updates_plist).AndReturn(None)
appleupdates.os.unlink(self.au.apple_updates_plist).AndReturn(None)
appleupdates.os.unlink(
self.au.applicable_updates_plist).AndRaise(OSError)
appleupdates.os.unlink(self.au.apple_updates_plist).AndReturn(None)
appleupdates.os.unlink(
self.au.applicable_updates_plist).AndRaise(IOError)
appleupdates.os.unlink(self.au.apple_updates_plist).AndRaise(OSError)
appleupdates.os.unlink(self.au.apple_updates_plist).AndRaise(IOError)
self.mox.ReplayAll()
self.au.ClearAppleUpdateInfo()
self.au.ClearAppleUpdateInfo()
self.au.ClearAppleUpdateInfo()
self.au.ClearAppleUpdateInfo()
self.au.ClearAppleUpdateInfo()
self.mox.VerifyAll()
def testDownloadAvailableUpdates(self):
"""Tests DownloadAvailableUpdates()."""
self._MockMunkiDisplay()
self.mox.StubOutWithMock(self.au, '_ResetMunkiStatusAndDisplayMessage')
self.mox.StubOutWithMock(self.au, '_RunSoftwareUpdate')
self.mox.StubOutWithMock(appleupdates.os.path, 'exists')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'getOsVersion')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'stopRequested')
msg = 'Downloading available Apple Software Updates...'
catalog_url = 'file://localhost' + appleupdates.urllib2.quote(
self.au.local_download_catalog_path)
self.au._ResetMunkiStatusAndDisplayMessage(msg).AndReturn(None)
appleupdates.os.path.exists(
self.au.local_download_catalog_path).AndReturn(True)
appleupdates.munkicommon.getOsVersion().AndReturn('10.7')
self.au._RunSoftwareUpdate(
['-d', '-a'],
catalog_url=catalog_url,
stop_allowed=True).AndReturn(0)
appleupdates.munkicommon.stopRequested().AndReturn(False)
self.mox.ReplayAll()
self.assertTrue(self.au.DownloadAvailableUpdates())
self.mox.VerifyAll()
def testDownloadAvailableUpdatesLeopard(self):
"""Tests DownloadAvailableUpdates() with Leopard."""
self._MockMunkiDisplay()
self.mox.StubOutWithMock(self.au, '_ResetMunkiStatusAndDisplayMessage')
self.mox.StubOutWithMock(self.au, '_LeopardDownloadAvailableUpdates')
self.mox.StubOutWithMock(appleupdates.os.path, 'exists')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'getOsVersion')
catalog_url = 'file://localhost' + appleupdates.urllib2.quote(
self.au.local_download_catalog_path)
msg = 'Downloading available Apple Software Updates...'
self.au._ResetMunkiStatusAndDisplayMessage(msg).AndReturn(None)
appleupdates.os.path.exists(
self.au.local_download_catalog_path).AndReturn(True)
appleupdates.munkicommon.getOsVersion().AndReturn('10.5')
self.au._LeopardDownloadAvailableUpdates(catalog_url).AndReturn(2)
appleupdates.munkicommon.display_error('softwareupdate error: %s' % 2)
self.mox.ReplayAll()
self.assertFalse(self.au.DownloadAvailableUpdates())
self.mox.VerifyAll()
def testDownloadAvailableUpdatesMissingCatalog(self):
"""Tests DownloadAvailableUpdates() with a missing catalog."""
self._MockMunkiDisplay()
self.mox.StubOutWithMock(self.au, '_ResetMunkiStatusAndDisplayMessage')
self.mox.StubOutWithMock(appleupdates.os.path, 'exists')
msg = 'Downloading available Apple Software Updates...'
self.au._ResetMunkiStatusAndDisplayMessage(msg).AndReturn(None)
appleupdates.os.path.exists(
self.au.local_download_catalog_path).AndReturn(False)
appleupdates.munkicommon.display_error(
'Missing local Software Update catalog at %s',
self.au.local_download_catalog_path)
self.mox.ReplayAll()
self.assertFalse(self.au.DownloadAvailableUpdates())
self.mox.VerifyAll()
def testGetAvailableUpdateProductIDsFailedSoftwareUpdate(self):
"""Tests GetAvailableUpdateProductIDs() with failed softwareupdate."""
self._MockMunkiDisplay()
self.mox.StubOutWithMock(self.au, '_RunSoftwareUpdate')
self.mox.StubOutWithMock(self.au, '_ResetMunkiStatusAndDisplayMessage')
self.mox.StubOutWithMock(appleupdates.os, 'unlink')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'getOsVersion')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'stopRequested')
msg = 'Checking for available Apple Software Updates...'
self.au._ResetMunkiStatusAndDisplayMessage(msg)
appleupdates.os.unlink(self.au.applicable_updates_plist).AndRaise(
OSError)
catalog_url = 'file://localhost' + appleupdates.urllib2.quote(
self.au.extracted_catalog_path)
self.au._RunSoftwareUpdate(
['-l', '-f', self.au.applicable_updates_plist],
catalog_url=catalog_url,
stop_allowed=True).AndReturn(1)
appleupdates.munkicommon.getOsVersion().AndReturn('10.6')
appleupdates.munkicommon.display_error('softwareupdate error: %s' % 1)
appleupdates.munkicommon.stopRequested().AndReturn(False)
self.mox.ReplayAll()
output = self.au.GetAvailableUpdateProductIDs()
self.assertEqual(output, [])
self.mox.VerifyAll()
def testGetAvailableUpdateProductIDsFailureReadingApplicableUpdates(self):
"""Tests GetAvailableUpdateProductIDs() failed applicable updates."""
self._MockFoundationPlist()
self.mox.StubOutWithMock(self.au, '_RunSoftwareUpdate')
self.mox.StubOutWithMock(self.au, '_ResetMunkiStatusAndDisplayMessage')
self.mox.StubOutWithMock(appleupdates.os, 'unlink')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'getOsVersion')
msg = 'Checking for available Apple Software Updates...'
self.au._ResetMunkiStatusAndDisplayMessage(msg)
appleupdates.os.unlink(self.au.applicable_updates_plist).AndRaise(
OSError)
catalog_url = 'file://localhost' + appleupdates.urllib2.quote(
self.au.extracted_catalog_path)
self.au._RunSoftwareUpdate(
['-l', '-f', self.au.applicable_updates_plist],
catalog_url=catalog_url,
stop_allowed=True).AndReturn(0)
exc = appleupdates.FoundationPlist.NSPropertyListSerializationException
appleupdates.FoundationPlist.readPlist(
self.au.applicable_updates_plist).AndRaise(exc)
self.mox.ReplayAll()
output = self.au.GetAvailableUpdateProductIDs()
self.assertEqual(output, [])
self.mox.VerifyAll()
def testGetAvailableUpdateProductIDsEmptyApplicableUpdates(self):
"""Tests GetAvailableUpdateProductIDs() empty applicable updates."""
self._MockFoundationPlist()
self.mox.StubOutWithMock(self.au, '_RunSoftwareUpdate')
self.mox.StubOutWithMock(self.au, '_ResetMunkiStatusAndDisplayMessage')
self.mox.StubOutWithMock(appleupdates.os, 'unlink')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'getOsVersion')
msg = 'Checking for available Apple Software Updates...'
self.au._ResetMunkiStatusAndDisplayMessage(msg)
appleupdates.os.unlink(self.au.applicable_updates_plist).AndRaise(
OSError)
catalog_url = 'file://localhost' + appleupdates.urllib2.quote(
self.au.extracted_catalog_path)
self.au._RunSoftwareUpdate(
['-l', '-f', self.au.applicable_updates_plist],
catalog_url=catalog_url,
stop_allowed=True).AndReturn(0)
appleupdates.FoundationPlist.readPlist(
self.au.applicable_updates_plist).AndReturn({})
self.mox.ReplayAll()
output = self.au.GetAvailableUpdateProductIDs()
self.assertEqual(output, [])
self.mox.VerifyAll()
def testGetAvailableUpdateProductIDsSuccess(self):
"""Tests GetAvailableUpdateProductIDs()."""
self._MockFoundationPlist()
self.mox.StubOutWithMock(self.au, '_RunSoftwareUpdate')
self.mox.StubOutWithMock(self.au, '_ResetMunkiStatusAndDisplayMessage')
self.mox.StubOutWithMock(appleupdates.os, 'unlink')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'getOsVersion')
updates_plist_dict = {
'phaseResultsArray': [
{'productKey': '4zzz'},
{'noProductKeyHere': True},
{'productKey': 'zzz5'},
]
}
msg = 'Checking for available Apple Software Updates...'
self.au._ResetMunkiStatusAndDisplayMessage(msg)
appleupdates.os.unlink(self.au.applicable_updates_plist).AndRaise(
OSError)
catalog_url = 'file://localhost' + appleupdates.urllib2.quote(
self.au.extracted_catalog_path)
self.au._RunSoftwareUpdate(
['-l', '-f', self.au.applicable_updates_plist],
catalog_url=catalog_url,
stop_allowed=True).AndReturn(0)
appleupdates.FoundationPlist.readPlist(
self.au.applicable_updates_plist).AndReturn(updates_plist_dict)
self.mox.ReplayAll()
output = self.au.GetAvailableUpdateProductIDs()
self.assertEqual(len(output), 2)
self.assertTrue('4zzz' in output)
self.assertTrue('zzz5' in output)
self.mox.VerifyAll()
def testExtractAndCopyDownloadedCatalogMakedirsError(self):
"""Tests ExtractAndCopyDownloadedCatalog() with os.makedirs error."""
self.mox.StubOutWithMock(appleupdates.os, 'makedirs')
self.mox.StubOutWithMock(appleupdates.os.path, 'exists')
appleupdates.os.path.exists(self.au.local_catalog_dir).AndReturn(False)
appleupdates.os.makedirs(self.au.local_catalog_dir).AndRaise(
OSError)
self.mox.ReplayAll()
self.assertRaises(
appleupdates.ReplicationError,
self.au.ExtractAndCopyDownloadedCatalog)
self.mox.VerifyAll()
def testExtractAndCopyDownloadedCatalogPlaintextCatalog(self):
"""Tests ExtractAndCopyDownloadedCatalog() with plain-text catalog."""
self.mox.StubOutWithMock(appleupdates.os.path, 'exists')
appleupdates.os.path.exists(self.au.local_catalog_dir).AndReturn(True)
local_apple_sus_catalog = appleupdates.os.path.join(
self.au.local_catalog_dir,
appleupdates.APPLE_EXTRACTED_CATALOG_NAME)
contents = 'non-gzipped text'
mock_open = self.mox.CreateMockAnything()
mock_file = self.mox.CreateMockAnything()
mock_open(self.au.apple_download_catalog_path, 'rb').AndReturn(
mock_file)
mock_file.read(2).AndReturn(contents)
mock_file.seek(0).AndReturn(None)
mock_file.read().AndReturn(contents)
mock_file.close().AndReturn(None)
mock_open(local_apple_sus_catalog, 'wb').AndReturn(mock_file)
mock_file.write(contents)
mock_file.close()
self.mox.ReplayAll()
self.au.ExtractAndCopyDownloadedCatalog(_open=mock_open)
self.mox.VerifyAll()
def testExtractAndCopyDownloadedCatalogGzippedCatalog(self):
"""Tests ExtractAndCopyDownloadedCatalog() with gzipped catalog."""
self.mox.StubOutWithMock(appleupdates.os.path, 'exists')
self.mox.StubOutWithMock(appleupdates.gzip, 'open')
appleupdates.os.path.exists(self.au.local_catalog_dir).AndReturn(True)
local_apple_sus_catalog = appleupdates.os.path.join(
self.au.local_catalog_dir,
appleupdates.APPLE_EXTRACTED_CATALOG_NAME)
contents = 'gzipped text'
mock_open = self.mox.CreateMockAnything()
mock_file = self.mox.CreateMockAnything()
mock_open(self.au.apple_download_catalog_path, 'rb').AndReturn(
mock_file)
mock_file.read(2).AndReturn('\x1f\x8b')
mock_file.close().AndReturn(None)
appleupdates.gzip.open(
self.au.apple_download_catalog_path, 'rb').AndReturn(mock_file)
mock_file.read().AndReturn(contents)
mock_file.close()
mock_open(local_apple_sus_catalog, 'wb').AndReturn(mock_file)
mock_file.write(contents)
mock_file.close()
self.mox.ReplayAll()
self.au.ExtractAndCopyDownloadedCatalog(_open=mock_open)
self.mox.VerifyAll()
def testGetAppleCatalogURLMunki(self):
"""Tests _GetAppleCatalogURL() with Munki's pref."""
self.mox.StubOutWithMock(appleupdates.munkicommon, 'pref')
appleupdates.munkicommon.pref('SoftwareUpdateServerURL').AndReturn(
'url')
self.mox.ReplayAll()
self.assertEqual('url', self.au._GetAppleCatalogURL())
self.mox.VerifyAll()
def testGetAppleCatalogURLSoftwareUpdateOrMCX(self):
"""Tests _GetAppleCatalogURL() with SoftwareUpdate.plist or MCX pref."""
self.mox.StubOutWithMock(self.au, 'GetSoftwareUpdatePref')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'pref')
appleupdates.munkicommon.pref('SoftwareUpdateServerURL').AndReturn(None)
self.au.GetSoftwareUpdatePref('CatalogURL').AndReturn('url')
self.mox.ReplayAll()
self.assertEqual('url', self.au._GetAppleCatalogURL())
self.mox.VerifyAll()
def testGetAppleCatalogURLDefault(self):
"""Tests _GetAppleCatalogURL() with default URL."""
self.mox.StubOutWithMock(self.au, 'GetSoftwareUpdatePref')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'pref')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'getOsVersion')
# Grab the first os_version/url combo to use for this test.
os_version = appleupdates.DEFAULT_CATALOG_URLS.keys()[0]
url = appleupdates.DEFAULT_CATALOG_URLS[os_version]
appleupdates.munkicommon.pref('SoftwareUpdateServerURL').AndReturn(None)
self.au.GetSoftwareUpdatePref('CatalogURL').AndReturn(None)
appleupdates.munkicommon.getOsVersion().AndReturn(os_version)
self.mox.ReplayAll()
self.assertEqual(url, self.au._GetAppleCatalogURL())
self.mox.VerifyAll()
def testGetAppleCatalogURLNotFound(self):
"""Tests _GetAppleCatalogURL() when the catalog URL is not found."""
self.mox.StubOutWithMock(self.au, 'GetSoftwareUpdatePref')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'pref')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'getOsVersion')
appleupdates.munkicommon.pref('SoftwareUpdateServerURL').AndReturn(None)
self.au.GetSoftwareUpdatePref('CatalogURL').AndReturn(None)
appleupdates.munkicommon.getOsVersion().AndReturn('UKNOWN OS VERSION!')
self.mox.ReplayAll()
self.assertRaises(
appleupdates.CatalogNotFoundError, self.au._GetAppleCatalogURL)
self.mox.VerifyAll()
def testCacheAppleCatalog(self):
"""Tests CacheAppleCatalog()."""
self._MockMunkiDisplay()
self.mox.StubOutWithMock(self.au, '_GetAppleCatalogURL')
self.mox.StubOutWithMock(self.au, 'ExtractAndCopyDownloadedCatalog')
self.mox.StubOutWithMock(appleupdates.os, 'makedirs')
self.mox.StubOutWithMock(appleupdates.os.path, 'exists')
self.mox.StubOutWithMock(self.au, 'GetSoftwareUpdateResource')
url = 'url'
self.au._GetAppleCatalogURL().AndReturn(url)
appleupdates.os.path.exists(self.au.temp_cache_dir).AndReturn(False)
appleupdates.os.makedirs(self.au.temp_cache_dir).AndReturn(None)
appleupdates.munkicommon.display_status_major(
'Checking Apple Software Update catalog...')
appleupdates.munkicommon.display_detail(
'Caching CatalogURL %s', url)
self.au.GetSoftwareUpdateResource(
url, self.au.apple_download_catalog_path, resume=True).AndReturn(
0)
self.au.ExtractAndCopyDownloadedCatalog().AndReturn(None)
self.mox.ReplayAll()
self.au.CacheAppleCatalog()
self.mox.VerifyAll()
def testCacheAppleCatalogWithBadCatalogURL(self):
"""Tests CacheAppleCatalog() with a bad catalog URL."""
self._MockMunkiDisplay()
self.mox.StubOutWithMock(self.au, '_GetAppleCatalogURL')
exc = appleupdates.CatalogNotFoundError('foo error')
self.au._GetAppleCatalogURL().AndRaise(exc)
appleupdates.munkicommon.display_error('foo error')
self.mox.ReplayAll()
self.assertRaises(
appleupdates.CatalogNotFoundError, self.au.CacheAppleCatalog)
self.mox.VerifyAll()
def testCacheAppleCatalogMakedirsError(self):
"""Tests CacheAppleCatalog() with os.makedirs error."""
self._MockMunkiDisplay()
self.mox.StubOutWithMock(self.au, '_GetAppleCatalogURL')
self.mox.StubOutWithMock(appleupdates.os, 'makedirs')
self.mox.StubOutWithMock(appleupdates.os.path, 'exists')
self.au._GetAppleCatalogURL().AndReturn('url')
appleupdates.os.path.exists(self.au.temp_cache_dir).AndReturn(False)
appleupdates.os.makedirs(self.au.temp_cache_dir).AndRaise(OSError)
self.mox.ReplayAll()
self.assertRaises(
appleupdates.ReplicationError, self.au.CacheAppleCatalog)
self.mox.VerifyAll()
def testCacheAppleCatalogMunkiDownloadError(self):
"""Tests CacheAppleCatalog() with a MunkiDownloadError."""
self._MockMunkiDisplay()
self.mox.StubOutWithMock(self.au, '_GetAppleCatalogURL')
self.mox.StubOutWithMock(self.au, 'ExtractAndCopyDownloadedCatalog')
self.mox.StubOutWithMock(appleupdates.os, 'makedirs')
self.mox.StubOutWithMock(appleupdates.os.path, 'exists')
self.mox.StubOutWithMock(self.au, 'GetSoftwareUpdateResource')
url = 'url'
self.au._GetAppleCatalogURL().AndReturn(url)
appleupdates.os.path.exists(self.au.temp_cache_dir).AndReturn(False)
appleupdates.os.makedirs(self.au.temp_cache_dir).AndReturn(None)
appleupdates.munkicommon.display_status_major(
'Checking Apple Software Update catalog...')
appleupdates.munkicommon.display_detail(
'Caching CatalogURL %s', url)
self.au.GetSoftwareUpdateResource(
url, self.au.apple_download_catalog_path, resume=True).AndRaise(
appleupdates.fetch.MunkiDownloadError)
self.mox.ReplayAll()
self.assertRaises(
appleupdates.fetch.MunkiDownloadError,
self.au.CacheAppleCatalog)
self.mox.VerifyAll()
def _InstalledApplePackagesHaveChangedHelper(
self, old_checksum, new_checksum):
"""Helper method for InstalledApplePackagesHaveChanged() testing."""
self.mox.StubOutWithMock(appleupdates.subprocess, 'Popen')
self.mox.StubOutWithMock(appleupdates.hashlib, 'sha256')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'pref')
cmd = ['/usr/sbin/pkgutil', '--regexp', '--pkg-info-plist',
'com\.apple\.*']
output = 'output!'
mock_proc = self.mox.CreateMockAnything()
appleupdates.subprocess.Popen(
cmd, shell=False, bufsize=1,
stdin=appleupdates.subprocess.PIPE,
stdout=appleupdates.subprocess.PIPE,
stderr=appleupdates.subprocess.PIPE).AndReturn(mock_proc)
mock_proc.communicate().AndReturn((output, 'unused foo'))
mock_hash = self.mox.CreateMockAnything()
appleupdates.hashlib.sha256(output).AndReturn(mock_hash)
mock_hash.hexdigest().AndReturn(new_checksum)
appleupdates.munkicommon.pref(
'InstalledApplePackagesChecksum').AndReturn(old_checksum)
if old_checksum != new_checksum:
self.mox.StubOutWithMock(appleupdates.munkicommon, 'set_pref')
appleupdates.munkicommon.set_pref(
'InstalledApplePackagesChecksum', new_checksum)
self.mox.ReplayAll()
if old_checksum == new_checksum:
self.assertFalse(self.au.InstalledApplePackagesHaveChanged())
else:
self.assertTrue(self.au.InstalledApplePackagesHaveChanged())
self.mox.VerifyAll()
def testInstalledApplePackagesHaveChangedWhenNoChange(self):
"""Tests InstalledApplePackagesHaveChanged() when haven't changed."""
self._InstalledApplePackagesHaveChangedHelper('zzzz', 'zzzz')
def testInstalledApplePackagesHaveChangedWhenChanged(self):
"""Tests InstalledApplePackagesHaveChanged() when they have changed."""
self._InstalledApplePackagesHaveChangedHelper('asdf', 'zzzz')
def testAvailableUpdatesAreDownloadedNoUpdateInfo(self):
"""Tests AvailableUpdatesAreDownloaded() when update info is empty."""
self.mox.StubOutWithMock(self.au, 'GetSoftwareUpdateInfo')
self.au.GetSoftwareUpdateInfo().AndReturn(None)
self.mox.ReplayAll()
self.assertTrue(self.au.AvailableUpdatesAreDownloaded())
self.mox.VerifyAll()
def testIsForceCheckNeccessaryWithChangedHash(self):
"""Tests _IsForceCheckNeccessary() when the hash has changed."""
self.mox.StubOutWithMock(appleupdates.munkicommon, 'getsha256hash')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'log')
appleupdates.munkicommon.getsha256hash(
self.au.apple_download_catalog_path).AndReturn('omg changed hash')
appleupdates.munkicommon.log('Apple update catalog has changed.')
self.mox.ReplayAll()
self.assertTrue(self.au._IsForceCheckNeccessary('outdated hash'))
self.mox.VerifyAll()
def testIsForceCheckNeccessaryWhenInstalledPackagesHaveChanged(self):
"""Tests _IsForceCheckNeccessary() when installed pkgs have changed."""
self.mox.StubOutWithMock(appleupdates.munkicommon, 'getsha256hash')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'log')
self.mox.StubOutWithMock(self.au, 'InstalledApplePackagesHaveChanged')
appleupdates.munkicommon.getsha256hash(
self.au.apple_download_catalog_path).AndReturn('hash')
self.au.InstalledApplePackagesHaveChanged().AndReturn(True)
appleupdates.munkicommon.log('Installed Apple packages have changed.')
self.mox.ReplayAll()
self.assertTrue(self.au._IsForceCheckNeccessary('hash'))
self.mox.VerifyAll()
def testIsForceCheckNeccessaryWhenAvailableUpdatesAreNotDownloaded(self):
"""Tests _IsForceCheckNeccessary(); new updates aren't downloaded."""
self.mox.StubOutWithMock(appleupdates.munkicommon, 'getsha256hash')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'log')
self.mox.StubOutWithMock(self.au, 'InstalledApplePackagesHaveChanged')
self.mox.StubOutWithMock(self.au, 'AvailableUpdatesAreDownloaded')
appleupdates.munkicommon.getsha256hash(
self.au.apple_download_catalog_path).AndReturn('hash')
self.au.InstalledApplePackagesHaveChanged().AndReturn(False)
self.au.AvailableUpdatesAreDownloaded().AndReturn(False)
appleupdates.munkicommon.log(
'Downloaded updates do not match our list of available updates.')
self.mox.ReplayAll()
self.assertTrue(self.au._IsForceCheckNeccessary('hash'))
self.mox.VerifyAll()
def testIsForceCheckNeccessaryWhenForceIsNotNeeded(self):
"""Tests _IsForceCheckNeccessary() when force is not needed."""
self.mox.StubOutWithMock(appleupdates.munkicommon, 'getsha256hash')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'log')
self.mox.StubOutWithMock(self.au, 'InstalledApplePackagesHaveChanged')
self.mox.StubOutWithMock(self.au, 'AvailableUpdatesAreDownloaded')
appleupdates.munkicommon.getsha256hash(
self.au.apple_download_catalog_path).AndReturn('hash')
self.au.InstalledApplePackagesHaveChanged().AndReturn(False)
self.au.AvailableUpdatesAreDownloaded().AndReturn(True)
self.mox.ReplayAll()
self.assertFalse(self.au._IsForceCheckNeccessary('hash'))
self.mox.VerifyAll()
def _CheckForSoftwareUpdatesCacheAppleCatalogExceptionHelper(
self, exc, s=''):
"""Helper method for CheckForSoftwareUpdates() exception handling."""
self._MockMunkiDisplay()
self.mox.StubOutWithMock(appleupdates.munkicommon, 'getsha256hash')
self.mox.StubOutWithMock(self.au, 'CacheAppleCatalog')
appleupdates.munkicommon.getsha256hash(
self.au.apple_download_catalog_path).AndReturn(None)
self.au.CacheAppleCatalog().AndRaise(exc(s))
if exc == appleupdates.ReplicationError or \
exc == appleupdates.fetch.MunkiDownloadError:
appleupdates.munkicommon.display_warning(
'Could not download Apple SUS catalog:')
appleupdates.munkicommon.display_warning('\t%s', s)
self.mox.ReplayAll()
self.assertFalse(self.au.CheckForSoftwareUpdates())
self.mox.VerifyAll()
def testCheckForSoftwareUpdatesCatalogNotFound(self):
"""Tests CheckForSoftwareUpdates() with CatalogNotFoundError."""
self._CheckForSoftwareUpdatesCacheAppleCatalogExceptionHelper(
appleupdates.CatalogNotFoundError)
def testCheckForSoftwareUpdatesReplicationError(self):
"""Tests CheckForSoftwareUpdates() with ReplicationError."""
self._CheckForSoftwareUpdatesCacheAppleCatalogExceptionHelper(
appleupdates.ReplicationError, s='foo error')
def testCheckForSoftwareUpdatesMunkiDownloadError(self):
"""Tests CheckForSoftwareUpdates() with MunkiDownloadError."""
self._CheckForSoftwareUpdatesCacheAppleCatalogExceptionHelper(
appleupdates.fetch.MunkiDownloadError)
def testCheckForSoftwareUpdatesWhenForceCheckNotNeeded(self):
"""Tests CheckForSoftwareUpdates() when a force check is not needed."""
self._MockMunkiDisplay()
self.mox.StubOutWithMock(appleupdates.munkicommon, 'getsha256hash')
self.mox.StubOutWithMock(self.au, 'CacheAppleCatalog')
self.mox.StubOutWithMock(self.au, '_IsForceCheckNeccessary')
self.mox.StubOutWithMock(self.au, 'GetSoftwareUpdateInfo')
appleupdates.munkicommon.getsha256hash(
self.au.apple_download_catalog_path).AndReturn('hash')
self.au.CacheAppleCatalog().AndReturn(None)
self.au._IsForceCheckNeccessary('hash').AndReturn(False)
appleupdates.munkicommon.display_info(
'Skipping Apple Software Update check because sucatalog is '
'unchanged, installed Apple packages are unchanged and we '
'recently did a full check.')
# mock out GetSoftwareUpdateInfo() because its return value
# depends on whether or not we have cached updates
# this implies we might need some tests that deal with
# cached updates...
self.au.GetSoftwareUpdateInfo().AndReturn(False)
self.mox.ReplayAll()
self.assertFalse(self.au.CheckForSoftwareUpdates(force_check=False))
self.mox.VerifyAll()
def testCheckForSoftwareUpdatesWhenUpdateListEmpty(self):
"""Tests CheckForSoftwareUpdates() when updatelist is empty."""
self.mox.StubOutWithMock(self.au, 'CacheAppleCatalog')
self.mox.StubOutWithMock(self.au, 'GetAvailableUpdateProductIDs')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'getsha256hash')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'set_pref')
# Cannot stub out the builtin date() method, so stub the entire module.
mock_nsdate_module = self.mox.CreateMockAnything()
self.mox.StubOutWithMock(appleupdates, 'NSDate', mock_nsdate_module)
mock_nsdate_module.date = self.mox.CreateMockAnything()
appleupdates.munkicommon.getsha256hash(
self.au.apple_download_catalog_path).AndReturn('hash')
self.au.CacheAppleCatalog().AndReturn(None)
self.au.GetAvailableUpdateProductIDs().AndReturn([])
appleupdates.NSDate.date().AndReturn('d')
appleupdates.munkicommon.set_pref('LastAppleSoftwareUpdateCheck', 'd')
self.mox.ReplayAll()
self.assertFalse(self.au.CheckForSoftwareUpdates())
self.mox.VerifyAll()
def testCheckForSoftwareUpdatesWhenCacheUpdateMetadataError(self):
"""Tests CheckForSoftwareUpdates() when CacheUpdateMetadata() fails."""
self._MockMunkiDisplay()
self.mox.StubOutWithMock(self.au, 'CacheAppleCatalog')
self.mox.StubOutWithMock(self.au, 'GetAvailableUpdateProductIDs')
self.mox.StubOutWithMock(self.au, '_WriteFilteredCatalog')
self.mox.StubOutWithMock(self.au, 'CacheUpdateMetadata')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'getsha256hash')
update_list = ['non-empty list']
appleupdates.munkicommon.getsha256hash(
self.au.apple_download_catalog_path).AndReturn('hash')
self.au.CacheAppleCatalog().AndReturn(None)
self.au.GetAvailableUpdateProductIDs().AndReturn(update_list)
self.au._WriteFilteredCatalog(
update_list, self.au.filtered_catalog_path).AndReturn(None)
exc = appleupdates.ReplicationError('foo err')
self.au.CacheUpdateMetadata().AndRaise(exc)
appleupdates.munkicommon.display_warning(
'Could not replicate software update metadata:')
appleupdates.munkicommon.display_warning('\t%s', 'foo err')
self.mox.ReplayAll()
self.assertFalse(self.au.CheckForSoftwareUpdates())
self.mox.VerifyAll()
def testCheckForSoftwareUpdatesWhenDownloadAvailableUpdateFails(self):
"""Tests CheckForSoftwareUpdates() when DownloadAvailUpdates() fails."""
self._MockMunkiDisplay()
self.mox.StubOutWithMock(self.au, 'CacheAppleCatalog')
self.mox.StubOutWithMock(self.au, 'GetAvailableUpdateProductIDs')
self.mox.StubOutWithMock(self.au, '_WriteFilteredCatalog')
self.mox.StubOutWithMock(self.au, 'CacheUpdateMetadata')
self.mox.StubOutWithMock(self.au, 'DownloadAvailableUpdates')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'getsha256hash')
update_list = ['non-empty list']
appleupdates.munkicommon.getsha256hash(
self.au.apple_download_catalog_path).AndReturn('hash')
self.au.CacheAppleCatalog().AndReturn(None)
self.au.GetAvailableUpdateProductIDs().AndReturn(update_list)
self.au._WriteFilteredCatalog(
update_list, self.au.filtered_catalog_path).AndReturn(None)
self.au.CacheUpdateMetadata().AndReturn(None)
self.au.DownloadAvailableUpdates().AndReturn(False)
self.mox.ReplayAll()
self.assertFalse(self.au.CheckForSoftwareUpdates())
self.mox.VerifyAll()
def testCheckForSoftwareUpdatesSuccess(self):
"""Tests CheckForSoftwareUpdates() success."""
self._MockMunkiDisplay()
self.mox.StubOutWithMock(self.au, 'CacheAppleCatalog')
self.mox.StubOutWithMock(self.au, 'GetAvailableUpdateProductIDs')
self.mox.StubOutWithMock(self.au, '_WriteFilteredCatalog')
self.mox.StubOutWithMock(self.au, 'CacheUpdateMetadata')
self.mox.StubOutWithMock(self.au, 'DownloadAvailableUpdates')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'getsha256hash')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'set_pref')
# Cannot stub out the builtin date() method, so stub the entire module.
mock_nsdate_module = self.mox.CreateMockAnything()
self.mox.StubOutWithMock(appleupdates, 'NSDate', mock_nsdate_module)
mock_nsdate_module.date = self.mox.CreateMockAnything()
update_list = ['non-empty list']
appleupdates.munkicommon.getsha256hash(
self.au.apple_download_catalog_path).AndReturn('hash')
self.au.CacheAppleCatalog().AndReturn(None)
self.au.GetAvailableUpdateProductIDs().AndReturn(update_list)
self.au._WriteFilteredCatalog(
update_list, self.au.filtered_catalog_path).AndReturn(None)
self.au.CacheUpdateMetadata().AndReturn(None)
self.au.DownloadAvailableUpdates().AndReturn(True)
appleupdates.NSDate.date().AndReturn('d')
appleupdates.munkicommon.set_pref('LastAppleSoftwareUpdateCheck', 'd')
self.mox.ReplayAll()
self.assertTrue(self.au.CheckForSoftwareUpdates())
self.mox.VerifyAll()
def testAvailableUpdatesAreDownloadedFoundationPlistError(self):
"""Tests AvailableUpdatesAreDownloaded() when invalid index_plist."""
self._MockFoundationPlist()
self.mox.StubOutWithMock(self.au, 'GetSoftwareUpdateInfo')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'log')
index_plist = '/Library/Updates/index.plist'
self.au.GetSoftwareUpdateInfo().AndReturn(True)
exc = appleupdates.FoundationPlist.FoundationPlistException
appleupdates.FoundationPlist.readPlist(index_plist).AndRaise(exc)
appleupdates.munkicommon.log(
'Apple downloaded update index is invalid: %s' % index_plist)
self.mox.ReplayAll()
self.assertFalse(self.au.AvailableUpdatesAreDownloaded())
self.mox.VerifyAll()
def testAvailableUpdatesAreDownloadedWithProductIdNotDownloaded(self):
"""Tests AvailableUpdatesAreDownloaded(); product_id not downloaded."""
self._MockFoundationPlist()
self.mox.StubOutWithMock(self.au, 'GetSoftwareUpdateInfo')
self.mox.StubOutWithMock(appleupdates.os.path, 'isdir')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'log')
index_plist = '/Library/Updates/index.plist'
apple_updates = [
{'productKey': '1', 'name': 'name1'},
{'productKey': '999', 'name': 'name999'},
{'NOTproductKey': 'boo', 'name': 'nameboo'},
]
download_index = {
'ProductPaths': {
'1': 'path1', '3': 'path3', '5': 'path5',
}
}
self.au.GetSoftwareUpdateInfo().AndReturn(apple_updates)
exc = appleupdates.FoundationPlist.FoundationPlistException
appleupdates.FoundationPlist.readPlist(index_plist).AndReturn(
download_index)
appleupdates.os.path.isdir(os.path.join(
'/Library/Updates', 'path1')).AndReturn(True)
appleupdates.os.path.isdir('/Library/Updates/').AndReturn(True)
appleupdates.munkicommon.log(
'Apple Update product is not downloaded: %s' % 'name999')
self.mox.ReplayAll()
self.assertFalse(self.au.AvailableUpdatesAreDownloaded())
self.mox.VerifyAll()
def testAvailableUpdatesAreDownloadedWithNonExistentProductDir(self):
"""Tests AvailableUpdatesAreDownloaded(); non-existent product dir."""
self._MockFoundationPlist()
self.mox.StubOutWithMock(self.au, 'GetSoftwareUpdateInfo')
self.mox.StubOutWithMock(appleupdates.os.path, 'isdir')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'log')
index_plist = '/Library/Updates/index.plist'
apple_updates = [
{'productKey': '1', 'name': 'name1'},
{'productKey': '3', 'name': 'name3'},
{'NOTproductKey': 'boo', 'name': 'nameboo'},
]
download_index = {
'ProductPaths': {
'1': 'path1', '3': 'path3', '5': 'path5',
}
}
self.au.GetSoftwareUpdateInfo().AndReturn(apple_updates)
exc = appleupdates.FoundationPlist.FoundationPlistException
appleupdates.FoundationPlist.readPlist(index_plist).AndReturn(
download_index)
appleupdates.os.path.isdir(os.path.join(
'/Library/Updates', 'path1')).AndReturn(True)
appleupdates.os.path.isdir(os.path.join(
'/Library/Updates', 'path3')).AndReturn(False)
appleupdates.munkicommon.log(
'Apple Update product directory is missing: %s' % 'name3')
self.mox.ReplayAll()
self.assertFalse(self.au.AvailableUpdatesAreDownloaded())
self.mox.VerifyAll()
def testAvailableUpdatesAreDownloadedSuccess(self):
"""Tests AvailableUpdatesAreDownloaded() with success."""
self._MockFoundationPlist()
self.mox.StubOutWithMock(self.au, 'GetSoftwareUpdateInfo')
self.mox.StubOutWithMock(appleupdates.os.path, 'isdir')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'log')
index_plist = '/Library/Updates/index.plist'
apple_updates = [
{'productKey': '1', 'name': 'name1'},
{'productKey': '3', 'name': 'name3'},
{'NOTproductKey': 'boo', 'name': 'nameboo'},
]
download_index = {
'ProductPaths': {
'1': 'path1', '3': 'path3', '5': 'path5',
}
}
self.au.GetSoftwareUpdateInfo().AndReturn(apple_updates)
exc = appleupdates.FoundationPlist.FoundationPlistException
appleupdates.FoundationPlist.readPlist(index_plist).AndReturn(
download_index)
appleupdates.os.path.isdir(os.path.join(
'/Library/Updates', 'path1')).AndReturn(True)
appleupdates.os.path.isdir(os.path.join(
'/Library/Updates', 'path3')).AndReturn(True)
self.mox.ReplayAll()
self.assertTrue(self.au.AvailableUpdatesAreDownloaded())
self.mox.VerifyAll()
def testGetSoftwareUpdateInfo(self):
"""Tests GetSoftwareUpdateInfo()."""
self._MockFoundationPlist()
self.mox.StubOutWithMock(appleupdates.os.path, 'exists')
self.mox.StubOutWithMock(self.au, 'GetBlockingApps')
self.mox.StubOutWithMock(self.au, 'GetFirmwareAlertText')
blocking_apps = ['blocking1', 'blocking2']
applicable_updates = {
'phaseResultsArray': [
{'description': 'desc1', 'ignoreKey': 'name1',
'version': 'ver1', 'name': 'display_name1', 'sizeInKB': 1000,
'productKey': 'prodid1'},
{'description': 'desc2', 'ignoreKey': 'name2',
'version': 'ver2', 'name': 'display_name2', 'sizeInKB': 2000,
'productKey': 'prodid2', 'restartRequired': 'YES'},
]
}
expected_output = [
{'apple_product_name': 'display_name1',
'blocking_applications': blocking_apps,
'description': 'desc1',
'name': 'name1',
'version_to_install': 'ver1',
'display_name': 'display_name1',
'installed_size': 1000,
'productKey': 'prodid1'},
{'apple_product_name': 'display_name2',
'description': 'desc2',
'firmware_alert_text': 'This is a firmware update',
'name': 'name2',
'version_to_install': 'ver2',
'display_name': 'display_name2',
'installed_size': 2000,
'productKey': 'prodid2',
'RestartAction': 'RequireRestart'},
]
appleupdates.os.path.exists(self.au.applicable_updates_plist).AndReturn(
True)
appleupdates.FoundationPlist.readPlist(
self.au.applicable_updates_plist).AndReturn(applicable_updates)
self.au.GetBlockingApps(
applicable_updates['phaseResultsArray'][0]['productKey']).AndReturn(
blocking_apps)
self.au.GetFirmwareAlertText(
applicable_updates['phaseResultsArray'][0]['productKey']).AndReturn(
'')
self.au.GetBlockingApps(
applicable_updates['phaseResultsArray'][1]['productKey']).AndReturn(
[])
self.au.GetFirmwareAlertText(
applicable_updates['phaseResultsArray'][1]['productKey']).AndReturn(
'This is a firmware update')
self.mox.ReplayAll()
self.assertEqual(expected_output, self.au.GetSoftwareUpdateInfo())
self.mox.VerifyAll()
def testGetSoftwareUpdateInfoWhenApplicableUpdatesDoesntExist(self):
"""Tests GetSoftwareUpdateInfo(); Applicable Updates does not exist."""
self.mox.StubOutWithMock(appleupdates.os.path, 'exists')
appleupdates.os.path.exists(self.au.applicable_updates_plist).AndReturn(
False)
self.mox.ReplayAll()
self.assertEqual([], self.au.GetSoftwareUpdateInfo())
self.mox.VerifyAll()
def testWriteAppleUpdatesFile(self):
"""Tests WriteAppleUpdatesFile()."""
self._MockFoundationPlist()
self._MockUpdateCheck()
self.mox.StubOutWithMock(self.au, 'GetSoftwareUpdateInfo')
self.au.GetSoftwareUpdateInfo().AndReturn('appleupdates')
appleupdates.updatecheck.getPrimaryManifestCatalogs(
'', force_refresh=False).AndReturn(None)
appleupdates.FoundationPlist.writePlist(
{'AppleUpdates': 'appleupdates'},
self.au.apple_updates_plist).AndReturn(None)
self.mox.ReplayAll()
self.assertTrue(self.au.WriteAppleUpdatesFile() == len('appleupdates'))
self.mox.VerifyAll()
def testWriteAppleUpdatesFileFailure(self):
"""Tests WriteAppleUpdatesFile() with failure."""
self._MockFoundationPlist()
self._MockUpdateCheck()
self.mox.StubOutWithMock(self.au, 'GetSoftwareUpdateInfo')
self.mox.StubOutWithMock(appleupdates.os, 'unlink')
self.au.GetSoftwareUpdateInfo().AndReturn(None)
appleupdates.os.unlink(self.au.apple_updates_plist).AndRaise(OSError)
self.mox.ReplayAll()
self.assertTrue(self.au.WriteAppleUpdatesFile() == 0)
self.mox.VerifyAll()
def testDisplayAppleUpdateInfo(self):
"""Tests DisplayAppleUpdateInfo()."""
self._MockFoundationPlist()
self._MockMunkiDisplay()
appleupdates.munkicommon.report = {}
apple_updates = {'AppleUpdates': [
{'display_name': 'name1', 'version_to_install': 'ver1',
'RestartAction': 'RequireRestart'},
{'display_name': 'name2', 'version_to_install': 'ver2',
'RestartAction': 'RequireLogout'},
{'display_name': 'name3', 'version_to_install': 'ver3'},
]}
appleupdates.FoundationPlist.readPlist(
self.au.apple_updates_plist).AndReturn(apple_updates)
appleupdates.munkicommon.display_info(
'The following Apple Software Updates are available to install:')
appleupdates.munkicommon.display_info(' + %s-%s' % ('name1', 'ver1'))
appleupdates.munkicommon.display_info(' *Restart required')
appleupdates.munkicommon.display_info(' + %s-%s' % ('name2', 'ver2'))
appleupdates.munkicommon.display_info(' *Logout required')
appleupdates.munkicommon.display_info(' + %s-%s' % ('name3', 'ver3'))
self.mox.ReplayAll()
self.assertTrue(
'RestartRequired' not in appleupdates.munkicommon.report)
self.assertTrue('LogoutRequired' not in appleupdates.munkicommon.report)
self.au.DisplayAppleUpdateInfo()
self.assertTrue(appleupdates.munkicommon.report['RestartRequired'])
self.assertTrue(appleupdates.munkicommon.report['LogoutRequired'])
self.mox.VerifyAll()
def testDisplayAppleUpdateInfoWhenReadPlistFailed(self):
"""Tests DisplayAppleUpdateInfo() when readPlist() fails."""
self._MockFoundationPlist()
self._MockMunkiDisplay()
exc = appleupdates.FoundationPlist.FoundationPlistException
appleupdates.FoundationPlist.readPlist(
self.au.apple_updates_plist).AndRaise(exc)
appleupdates.munkicommon.display_error(
'Error reading: %s', self.au.apple_updates_plist)
self.mox.ReplayAll()
self.au.DisplayAppleUpdateInfo()
self.mox.VerifyAll()
def testGetSoftwareUpdatePref(self):
"""Tests GetSoftwareUpdatePref()."""
self.mox.StubOutWithMock(appleupdates, 'CFPreferencesCopyAppValue')
pref_name = 'foo'
expected_return = 'bar'
appleupdates.CFPreferencesCopyAppValue(
pref_name,
appleupdates.APPLE_SOFTWARE_UPDATE_PREFS_DOMAIN
).AndReturn(expected_return)
self.mox.ReplayAll()
self.au.GetSoftwareUpdatePref(pref_name)
self.mox.VerifyAll()
def testLeopardSetupSoftwareUpdateCheck(self):
"""Tests _LeopardSetupSoftwareUpdateCheck()."""
self._MockMunkiDisplay()
self.mox.StubOutWithMock(appleupdates, 'CFPreferencesSetValue')
self.mox.StubOutWithMock(appleupdates, 'CFPreferencesAppSynchronize')
appleupdates.CFPreferencesSetValue(
'AgreedToLicenseAgreement', True,
appleupdates.APPLE_SOFTWARE_UPDATE_PREFS_DOMAIN,
appleupdates.kCFPreferencesCurrentUser,
appleupdates.kCFPreferencesCurrentHost).AndReturn(None)
appleupdates.CFPreferencesSetValue(
'AutomaticDownload', True,
appleupdates.APPLE_SOFTWARE_UPDATE_PREFS_DOMAIN,
appleupdates.kCFPreferencesCurrentUser,
appleupdates.kCFPreferencesCurrentHost).AndReturn(None)
appleupdates.CFPreferencesSetValue(
'LaunchAppInBackground', True,
appleupdates.APPLE_SOFTWARE_UPDATE_PREFS_DOMAIN,
appleupdates.kCFPreferencesCurrentUser,
appleupdates.kCFPreferencesCurrentHost).AndReturn(None)
appleupdates.CFPreferencesAppSynchronize(
appleupdates.APPLE_SOFTWARE_UPDATE_PREFS_DOMAIN).AndReturn(None)
appleupdates.munkicommon.display_error(
'Error setting com.apple.SoftwareUpdate ByHost preferences.')
self.mox.ReplayAll()
self.au._LeopardSetupSoftwareUpdateCheck()
self.mox.VerifyAll()
# TODO(ogle): _LeopardDownloadAvailableUpdates, _RunSoftwareUpdate, and
# InstallAppleUpdates tests are missing here.
def testAppleSoftwareUpdatesAvailableWhenCheckNeeded(self):
"""Tests AppleSoftwareUpdatesAvailable() when check needed."""
self.mox.StubOutWithMock(appleupdates.munkicommon, 'stopRequested')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'pref')
self.mox.StubOutWithMock(self.au, 'CheckForSoftwareUpdates')
self.mox.StubOutWithMock(self.au, 'WriteAppleUpdatesFile')
#self.mox.StubOutWithMock(self.au, 'DisplayAppleUpdateInfo')
# Cannot stub out the builtin NSDate methods, so stub the entire module.
mock_nsdate_module = self.mox.CreateMockAnything()
self.mox.StubOutWithMock(appleupdates, 'NSDate', mock_nsdate_module)
mock_nsdate_new = self.mox.CreateMockAnything()
mock_nsdate_datewithstring = self.mox.CreateMockAnything()
mock_nsdate_module.new = mock_nsdate_new
mock_nsdate_module.dateWithString_ = mock_nsdate_datewithstring
now_nsdate = NSDate.dateWithString_('2011-08-22 18:00:00 -400')
appleupdates.NSDate.new().AndReturn(now_nsdate)
# use a date barely older than the 24 hour threshold.
recent_date_str = '2011-08-21 17:59:00 -0400'
recent_date_nsdate = NSDate.dateWithString_(recent_date_str)
appleupdates.munkicommon.pref('LastAppleSoftwareUpdateCheck').AndReturn(
recent_date_str)
appleupdates.NSDate.dateWithString_(recent_date_str).AndReturn(
recent_date_nsdate)
self.au.CheckForSoftwareUpdates(force_check=True).AndReturn(True)
appleupdates.munkicommon.stopRequested().AndReturn(False)
self.au.WriteAppleUpdatesFile().AndReturn(True)
#self.au.DisplayAppleUpdateInfo().AndReturn(None)
self.mox.ReplayAll()
out = self.au.AppleSoftwareUpdatesAvailable(
force_check=False, suppress_check=False)
self.assertTrue(out)
self.mox.VerifyAll()
def testAppleSoftwareUpdatesAvailableWhenRecentlyChecked(self):
"""Tests AppleSoftwareUpdatesAvailable() when recently check."""
self.mox.StubOutWithMock(appleupdates.munkicommon, 'stopRequested')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'pref')
self.mox.StubOutWithMock(self.au, 'CheckForSoftwareUpdates')
self.mox.StubOutWithMock(self.au, 'WriteAppleUpdatesFile')
#self.mox.StubOutWithMock(self.au, 'DisplayAppleUpdateInfo')
# Cannot stub out the builtin NSDate methods, so stub the entire module.
mock_nsdate_module = self.mox.CreateMockAnything()
self.mox.StubOutWithMock(appleupdates, 'NSDate', mock_nsdate_module)
mock_nsdate_new = self.mox.CreateMockAnything()
mock_nsdate_datewithstring = self.mox.CreateMockAnything()
mock_nsdate_module.new = mock_nsdate_new
mock_nsdate_module.dateWithString_ = mock_nsdate_datewithstring
now_nsdate = NSDate.dateWithString_('2011-08-22 18:00:00 -400')
appleupdates.NSDate.new().AndReturn(now_nsdate)
# use a date barely newer than the 24 hour threshold.
recent_date_str = '2011-08-21 18:01:00 -0400'
recent_date_nsdate = NSDate.dateWithString_(recent_date_str)
appleupdates.munkicommon.pref('LastAppleSoftwareUpdateCheck').AndReturn(
recent_date_str)
appleupdates.NSDate.dateWithString_(recent_date_str).AndReturn(
recent_date_nsdate)
self.au.CheckForSoftwareUpdates(force_check=False).AndReturn(True)
appleupdates.munkicommon.stopRequested().AndReturn(False)
self.au.WriteAppleUpdatesFile().AndReturn(True)
#self.au.DisplayAppleUpdateInfo().AndReturn(None)
self.mox.ReplayAll()
out = self.au.AppleSoftwareUpdatesAvailable(
force_check=False, suppress_check=False)
self.assertTrue(out)
self.mox.VerifyAll()
def testAppleSoftwareUpdatesAvailableWhenNsDateValueError(self):
"""Tests AppleSoftwareUpdatesAvailable() when ValueError is raised."""
self.mox.StubOutWithMock(appleupdates.munkicommon, 'stopRequested')
self.mox.StubOutWithMock(appleupdates.munkicommon, 'pref')
self.mox.StubOutWithMock(self.au, 'CheckForSoftwareUpdates')
self.mox.StubOutWithMock(self.au, 'WriteAppleUpdatesFile')
#self.mox.StubOutWithMock(self.au, 'DisplayAppleUpdateInfo')
# use a date string that will not parse correctly.
appleupdates.munkicommon.pref('LastAppleSoftwareUpdateCheck').AndReturn(
'zomg this is not a date!!!!!')
self.au.CheckForSoftwareUpdates(force_check=True).AndReturn(True)
appleupdates.munkicommon.stopRequested().AndReturn(False)
self.au.WriteAppleUpdatesFile().AndReturn(True)
#self.au.DisplayAppleUpdateInfo().AndReturn(None)
self.mox.ReplayAll()
out = self.au.AppleSoftwareUpdatesAvailable(
force_check=False, suppress_check=False)
self.assertTrue(out)
self.mox.VerifyAll()
def testAppleSoftwareUpdatesAvailableForceCheck(self):
"""Tests AppleSoftwareUpdatesAvailable() with force_check=True."""
self.mox.StubOutWithMock(appleupdates.munkicommon, 'stopRequested')
self.mox.StubOutWithMock(self.au, 'CheckForSoftwareUpdates')
self.mox.StubOutWithMock(self.au, 'WriteAppleUpdatesFile')
#self.mox.StubOutWithMock(self.au, 'DisplayAppleUpdateInfo')
self.au.CheckForSoftwareUpdates(force_check=True).AndReturn(True)
appleupdates.munkicommon.stopRequested().AndReturn(False)
self.au.WriteAppleUpdatesFile().AndReturn(True)
#self.au.DisplayAppleUpdateInfo().AndReturn(None)
self.mox.ReplayAll()
out = self.au.AppleSoftwareUpdatesAvailable(
force_check=True, suppress_check=False)
self.assertTrue(out)
self.mox.VerifyAll()
def testAppleSoftwareUpdatesAvailableSuppressCheck(self):
"""Tests AppleSoftwareUpdatesAvailable() with suppress_check=True."""
self.mox.StubOutWithMock(appleupdates.munkicommon, 'stopRequested')
self.mox.StubOutWithMock(self.au, 'WriteAppleUpdatesFile')
#self.mox.StubOutWithMock(self.au, 'DisplayAppleUpdateInfo')
appleupdates.munkicommon.stopRequested().AndReturn(False)
self.au.WriteAppleUpdatesFile().AndReturn(True)
#self.au.DisplayAppleUpdateInfo().AndReturn(None)
self.mox.ReplayAll()
out = self.au.AppleSoftwareUpdatesAvailable(
force_check=False, suppress_check=True)
self.assertTrue(out)
self.mox.VerifyAll()
def testAppleSoftwareUpdatesAvailableSuppressCheckNoneAvailable(self):
"""Tests AppleSoftwareUpdatesAvailable() when no updates available."""
self.mox.StubOutWithMock(appleupdates.munkicommon, 'stopRequested')
self.mox.StubOutWithMock(self.au, 'WriteAppleUpdatesFile')
#self.mox.StubOutWithMock(self.au, 'DisplayAppleUpdateInfo')
appleupdates.munkicommon.stopRequested().AndReturn(False)
self.au.WriteAppleUpdatesFile().AndReturn(False)
self.mox.ReplayAll()
out = self.au.AppleSoftwareUpdatesAvailable(
force_check=False, suppress_check=True)
self.assertFalse(out)
self.mox.VerifyAll()
def testSoftwareUpdateListCached(self):
"""Tests SoftwareUpdateList() when update list is cached."""
self.au._update_list_cache = 'not none'
output = self.au.SoftwareUpdateList()
self.assertEqual(output, self.au._update_list_cache)
def testSoftwareUpdateList(self):
"""Tests SoftwareUpdateList() success."""
self._MockMunkiDisplay()
self.mox.StubOutWithMock(appleupdates.subprocess, 'Popen')
process_output = (
' * Foo Package 1\n'
' * Bar Update 2\n'
' ignore more, because I do not start with " * "\n'
' * Zoo Install 3\n'
' * Security Patch!\n'
)
expected_output = [
'Foo Package 1', 'Bar Update 2', 'Zoo Install 3', 'Security Patch!'
]
appleupdates.munkicommon.display_detail(
'Getting list of available Apple Software Updates')
mock_process = self.mox.CreateMockAnything()
appleupdates.subprocess.Popen(
['/usr/sbin/softwareupdate', '-l'], shell=False, bufsize=-1,
stdin=appleupdates.subprocess.PIPE,
stdout=appleupdates.subprocess.PIPE,
stderr=appleupdates.subprocess.PIPE).AndReturn(mock_process)
mock_process.communicate().AndReturn((process_output, 'unused'))
mock_process.returncode = 0
appleupdates.munkicommon.display_detail(
'softwareupdate returned %d updates.', 4)
self.mox.ReplayAll()
output = self.au.SoftwareUpdateList()
self.assertTrue(self.au._update_list_cache is not None)
self.assertEqual(output, expected_output)
self.mox.VerifyAll()
class TestAppleUpdatesModule(mox.MoxTestBase):
"""Test appleupdates module."""
def setUp(self):
mox.MoxTestBase.setUp(self)
self.stubs = stubout.StubOutForTesting()
def tearDown(self):
self.mox.UnsetStubs()
self.stubs.UnsetAll()
def testGlobals(self):
"""Test global variables."""
self.assertTrue(
type(getattr(appleupdates, 'DEFAULT_CATALOG_URLS', None)) is dict)
def main():
unittest.main()
if __name__ == '__main__':
main()