Commit 333a5272 authored by Paul Jensen's avatar Paul Jensen Committed by Commit Bot

[Cronet] Add stamp to api.txt to prevent accidental bulk renames modifying API

Without a stamp a bulk rename could modify the Cronet API but pass through the
API static checks.  With the stamp, edits to api.txt must be done via update_api.py
which enforces the static checks.

Cq-Include-Trybots: master.tryserver.chromium.android:android_cronet_tester;master.tryserver.chromium.mac:ios-simulator-cronet
Change-Id: I01040c5e377bc6a0e8831c2bab30da5d460d6ae3
Reviewed-on: https://chromium-review.googlesource.com/1025644Reviewed-by: default avatarAndrei Kapishnikov <kapishnikov@chromium.org>
Commit-Queue: Paul Jensen <pauljensen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#553662}
parent 60713be4
...@@ -295,3 +295,4 @@ public abstract class org.chromium.net.UrlResponseInfo { ...@@ -295,3 +295,4 @@ public abstract class org.chromium.net.UrlResponseInfo {
public abstract java.lang.String getProxyServer(); public abstract java.lang.String getProxyServer();
public abstract long getReceivedByteCount(); public abstract long getReceivedByteCount();
} }
Stamp: f4909b6572d83edd28472e7087b0e6f2
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
import contextlib import contextlib
from cStringIO import StringIO from cStringIO import StringIO
import md5
import os import os
import shutil import shutil
import sys import sys
...@@ -74,7 +75,7 @@ class ApiStaticCheckUnitTest(unittest.TestCase): ...@@ -74,7 +75,7 @@ class ApiStaticCheckUnitTest(unittest.TestCase):
with open(API_VERSION_FILENAME, 'w') as api_version_file: with open(API_VERSION_FILENAME, 'w') as api_version_file:
api_version_file.write('0') api_version_file.write('0')
with open(API_FILENAME, 'w') as api_file: with open(API_FILENAME, 'w') as api_file:
api_file.write('}\n') api_file.write('}\nStamp: 7d9d25f71cb8a5aba86202540a20d405\n')
shutil.copytree(os.path.dirname(__file__), 'tools') shutil.copytree(os.path.dirname(__file__), 'tools')
...@@ -141,6 +142,15 @@ class ApiStaticCheckUnitTest(unittest.TestCase): ...@@ -141,6 +142,15 @@ class ApiStaticCheckUnitTest(unittest.TestCase):
api_version = api_version_file.read() api_version = api_version_file.read()
with open(OUT_FILENAME, 'r') as out_file: with open(OUT_FILENAME, 'r') as out_file:
output = out_file.read() output = out_file.read()
# Verify stamp
api_stamp = api.split('\n')[-2]
stamp_length = len('Stamp: 78418460c193047980ae9eabb79293f2\n')
api = api[:-stamp_length]
api_hash = md5.new()
api_hash.update(api)
self.assertEquals(api_stamp, 'Stamp: %s' % api_hash.hexdigest())
return [return_code == 0, output, api, api_version] return [return_code == 0, output, api, api_version]
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
import argparse import argparse
import filecmp import filecmp
import fileinput import fileinput
import md5
import os import os
import re import re
import shutil import shutil
...@@ -65,6 +66,7 @@ def generate_api(api_jar, output_filename): ...@@ -65,6 +66,7 @@ def generate_api(api_jar, output_filename):
# Strip out pieces we don't need to compare. # Strip out pieces we don't need to compare.
output_file = fileinput.FileInput(output_filename, inplace=True) output_file = fileinput.FileInput(output_filename, inplace=True)
skip_to_next_class = False skip_to_next_class = False
md5_hash = md5.new()
for line in output_file: for line in output_file:
# Skip 'Compiled from ' lines as they're not part of the API. # Skip 'Compiled from ' lines as they're not part of the API.
if line.startswith('Compiled from "'): if line.startswith('Compiled from "'):
...@@ -79,8 +81,11 @@ def generate_api(api_jar, output_filename): ...@@ -79,8 +81,11 @@ def generate_api(api_jar, output_filename):
if skip_to_next_class: if skip_to_next_class:
skip_to_next_class = line != '}' skip_to_next_class = line != '}'
continue continue
md5_hash.update(line)
sys.stdout.write(line) sys.stdout.write(line)
output_file.close() output_file.close()
with open(output_filename, 'a') as output_file:
output_file.write('Stamp: %s\n' % md5_hash.hexdigest())
return True return True
...@@ -97,17 +102,40 @@ def check_up_to_date(api_jar): ...@@ -97,17 +102,40 @@ def check_up_to_date(api_jar):
def check_api_update(old_api, new_api): def check_api_update(old_api, new_api):
# Enforce that lines are only added when updating API. # Enforce that lines are only added when updating API.
new_hash = md5.new()
old_hash = md5.new()
seen_stamp = False
with open(old_api, 'r') as old_api_file, open(new_api, 'r') as new_api_file: with open(old_api, 'r') as old_api_file, open(new_api, 'r') as new_api_file:
for old_line in old_api_file: for old_line in old_api_file:
while True: while True:
new_line = new_api_file.readline() new_line = new_api_file.readline()
if seen_stamp:
print 'ERROR: Stamp is not the last line.'
return False
if new_line.startswith('Stamp: ') and old_line.startswith('Stamp: '):
if old_line != 'Stamp: %s\n' % old_hash.hexdigest():
print 'ERROR: Prior api.txt not stamped by update_api.py'
return False
if new_line != 'Stamp: %s\n' % new_hash.hexdigest():
print 'ERROR: New api.txt not stamped by update_api.py'
return False
seen_stamp = True
break
new_hash.update(new_line)
if new_line == old_line: if new_line == old_line:
break break
if not new_line: if not new_line:
print 'ERROR: This API was modified or removed:' if old_line.startswith('Stamp: '):
print ' ' + old_line print 'ERROR: New api.txt not stamped by update_api.py'
print ' Cronet API methods and classes cannot be modified.' else:
print 'ERROR: This API was modified or removed:'
print ' ' + old_line
print ' Cronet API methods and classes cannot be modified.'
return False return False
old_hash.update(old_line)
if not seen_stamp:
print 'ERROR: api.txt not stamped by update_api.py.'
return False
return True return True
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment