cron_servlet_test.py revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
1b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#!/usr/bin/env python 2b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved. 3b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 4b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)# found in the LICENSE file. 5b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 6b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)import unittest 7b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 8a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)from appengine_wrappers import GetAppVersion 9a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)from app_yaml_helper import AppYamlHelper 10b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from cron_servlet import CronServlet 11b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from empty_dir_file_system import EmptyDirFileSystem 124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)from host_file_system_provider import HostFileSystemProvider 13b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from local_file_system import LocalFileSystem 14b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from mock_file_system import MockFileSystem 15b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from servlet import Request 16b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from test_branch_utility import TestBranchUtility 17b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from test_file_system import TestFileSystem 18b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)from test_util import EnableLogging 19b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 20b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)# NOTE(kalman): The ObjectStore created by the CronServlet is backed onto our 21a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)# fake AppEngine memcache/datastore, so the tests aren't isolated. Of course, 22a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)# if the host file systems have different identities, they will be, sort of. 23b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class _TestDelegate(CronServlet.Delegate): 24a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) def __init__(self, create_file_system): 25a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.file_systems = [] 26a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # A callback taking a revision and returning a file system. 27a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self._create_file_system = create_file_system 28a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self._app_version = GetAppVersion() 29b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 30b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def CreateBranchUtility(self, object_store_creator): 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return TestBranchUtility.CreateWithCannedData() 32b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) def CreateHostFileSystemProvider(self, 344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) object_store_creator, 354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) max_trunk_revision=None): 36ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch def constructor(branch=None, revision=None): 37ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch file_system = self._create_file_system(revision) 387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch self.file_systems.append(file_system) 397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return file_system 404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return HostFileSystemProvider(object_store_creator, 414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) max_trunk_revision=max_trunk_revision, 427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch constructor_for_test=constructor) 43b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 44b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def CreateAppSamplesFileSystem(self, object_store_creator): 45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return EmptyDirFileSystem() 46b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 47a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) def GetAppVersion(self): 48a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return self._app_version 49a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 50a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # (non-Delegate method). 51a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) def SetAppVersion(self, app_version): 52a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self._app_version = app_version 53a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 54b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)class CronServletTest(unittest.TestCase): 55b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) @EnableLogging('info') 56b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) def testEverything(self): 57b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # All these tests are dependent (see above comment) so lump everything in 58b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # the one test. 59ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch delegate = _TestDelegate(lambda _: MockFileSystem(LocalFileSystem.Create())) 60b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 61b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # Test that the cron runs successfully. 62b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) response = CronServlet(Request.ForTest('trunk'), 63b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) delegate_for_test=delegate).Get() 64b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) self.assertEqual(200, response.status) 65b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 66ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch # Save the file systems created, start with a fresh set for the next run. 67ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch first_run_file_systems = delegate.file_systems[:] 68ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch delegate.file_systems[:] = [] 69ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 70b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # When re-running, all file systems should be Stat()d the same number of 71b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # times, but the second round shouldn't have been re-Read() since the 72b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) # Stats haven't changed. 73b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) response = CronServlet(Request.ForTest('trunk'), 74b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) delegate_for_test=delegate).Get() 75ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch self.assertEqual(200, response.status) 76ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 77ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch self.assertEqual(len(first_run_file_systems), len(delegate.file_systems)) 78ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch for i, second_run_file_system in enumerate(delegate.file_systems): 79ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch self.assertTrue(*second_run_file_system.CheckAndReset( 80ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch read_count=0, 81ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch stat_count=first_run_file_systems[i].GetStatCount())) 82a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 83a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) def testSafeRevision(self): 84a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) test_data = { 85424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 'api': { 86424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) '_manifest_features.json': '{}' 87424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) }, 88a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 'docs': { 89a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 'examples': { 90a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 'examples.txt': 'examples.txt contents' 91a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) }, 92a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 'server2': { 93a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 'app.yaml': AppYamlHelper.GenerateAppYaml('2-0-8') 94a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) }, 95a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 'static': { 96a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 'static.txt': 'static.txt contents' 97a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) }, 98a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 'templates': { 99a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 'public': { 100a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 'apps': { 101a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 'storage.html': 'storage.html contents' 102a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) }, 103a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 'extensions': { 104a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 'storage.html': 'storage.html contents' 105a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) }, 1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }, 1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 'json': { 108424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 'manifest.json': '{}', 10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 'strings.json': '{}', 11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 'apps_sidenav.json': '{}', 11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 'extensions_sidenav.json': '{}', 1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) }, 113a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 114a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 115a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) } 116a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 117a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) updates = [] 118a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 119a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) def app_yaml_update(version): 120a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return {'docs': {'server2': { 121a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 'app.yaml': AppYamlHelper.GenerateAppYaml(version) 122a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) }}} 123a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) def storage_html_update(update): 124a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return {'docs': {'templates': {'public': {'apps': { 125a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 'storage.html': update 126a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) }}}}} 127a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) def static_txt_update(update): 128a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return {'docs': {'static': { 129a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 'static.txt': update 130a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) }}} 131a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 132a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) app_yaml_path = 'docs/server2/app.yaml' 133a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) storage_html_path = 'docs/templates/public/apps/storage.html' 134a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) static_txt_path = 'docs/static/static.txt' 135a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 136ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch def create_file_system(revision=None): 137a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) '''Creates a MockFileSystem at |revision| by applying that many |updates| 138a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) to it. 139a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ''' 140a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) mock_file_system = MockFileSystem(TestFileSystem(test_data)) 1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) updates_for_revision = ( 1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) updates if revision is None else updates[:int(revision)]) 1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for update in updates_for_revision: 144a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) mock_file_system.Update(update) 145a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return mock_file_system 146a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 147a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) delegate = _TestDelegate(create_file_system) 148a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) delegate.SetAppVersion('2-0-8') 149a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 150a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) file_systems = delegate.file_systems 151a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 152a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # No updates applied yet. 153a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) CronServlet(Request.ForTest('trunk'), delegate_for_test=delegate).Get() 154a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.assertEqual(AppYamlHelper.GenerateAppYaml('2-0-8'), 1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_systems[-1].ReadSingle(app_yaml_path).Get()) 156a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.assertEqual('storage.html contents', 1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_systems[-1].ReadSingle(storage_html_path).Get()) 158a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 159a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # Apply updates to storage.html. 160a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) updates.append(storage_html_update('interim contents')) 161a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) updates.append(storage_html_update('new contents')) 162a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 163a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) CronServlet(Request.ForTest('trunk'), delegate_for_test=delegate).Get() 164a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.assertEqual(AppYamlHelper.GenerateAppYaml('2-0-8'), 1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_systems[-1].ReadSingle(app_yaml_path).Get()) 166a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.assertEqual('new contents', 1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_systems[-1].ReadSingle(storage_html_path).Get()) 168a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 169a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # Apply several updates to storage.html and app.yaml. The file system 170a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # should be pinned at the version before app.yaml changed. 171a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) updates.append(storage_html_update('stuck here contents')) 172a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 173a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) double_update = storage_html_update('newer contents') 174a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) double_update.update(app_yaml_update('2-0-10')) 175a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) updates.append(double_update) 176a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 177a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) updates.append(storage_html_update('never gonna reach here')) 178a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 179a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) CronServlet(Request.ForTest('trunk'), delegate_for_test=delegate).Get() 180a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.assertEqual(AppYamlHelper.GenerateAppYaml('2-0-8'), 1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_systems[-1].ReadSingle(app_yaml_path).Get()) 182a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.assertEqual('stuck here contents', 1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_systems[-1].ReadSingle(storage_html_path).Get()) 184a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 185a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # Further pushes to storage.html will keep it pinned. 186a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) updates.append(storage_html_update('y u not update!')) 187a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 188a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) CronServlet(Request.ForTest('trunk'), delegate_for_test=delegate).Get() 189a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.assertEqual(AppYamlHelper.GenerateAppYaml('2-0-8'), 1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_systems[-1].ReadSingle(app_yaml_path).Get()) 191a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.assertEqual('stuck here contents', 1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_systems[-1].ReadSingle(storage_html_path).Get()) 193a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 194a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # Likewise app.yaml. 195a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) updates.append(app_yaml_update('2-1-0')) 196a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 197a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) CronServlet(Request.ForTest('trunk'), delegate_for_test=delegate).Get() 198a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.assertEqual(AppYamlHelper.GenerateAppYaml('2-0-8'), 1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_systems[-1].ReadSingle(app_yaml_path).Get()) 200a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.assertEqual('stuck here contents', 2014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_systems[-1].ReadSingle(storage_html_path).Get()) 202a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 203a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # And updates to other content won't happen either. 204a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) updates.append(static_txt_update('important content!')) 205a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 206a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) CronServlet(Request.ForTest('trunk'), delegate_for_test=delegate).Get() 207a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.assertEqual(AppYamlHelper.GenerateAppYaml('2-0-8'), 2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_systems[-1].ReadSingle(app_yaml_path).Get()) 209a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.assertEqual('stuck here contents', 2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_systems[-1].ReadSingle(storage_html_path).Get()) 211a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.assertEqual('static.txt contents', 2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_systems[-1].ReadSingle(static_txt_path).Get()) 213b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 214a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # Lastly - when the app version changes, everything should no longer be 215a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) # pinned. 216a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) delegate.SetAppVersion('2-1-0') 217a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) CronServlet(Request.ForTest('trunk'), delegate_for_test=delegate).Get() 218a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.assertEqual(AppYamlHelper.GenerateAppYaml('2-1-0'), 2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_systems[-1].ReadSingle(app_yaml_path).Get()) 220a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.assertEqual('y u not update!', 2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_systems[-1].ReadSingle(storage_html_path).Get()) 222a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) self.assertEqual('important content!', 2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) file_systems[-1].ReadSingle(static_txt_path).Get()) 224b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 225b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)if __name__ == '__main__': 226b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) unittest.main() 227