Skip to content

Commit

Permalink
Reland memory support (#349). r=nthomas
Browse files Browse the repository at this point in the history
  • Loading branch information
bhearsum committed Jul 19, 2017
1 parent 439a050 commit 6d1c9d1
Show file tree
Hide file tree
Showing 25 changed files with 454 additions and 301 deletions.
36 changes: 31 additions & 5 deletions auslib/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

from auslib.global_state import cache
from auslib.blobs.base import createBlob
from auslib.util.comparison import string_compare, version_compare
from auslib.util.comparison import string_compare, version_compare, int_compare
from auslib.util.timestamp import getMillisecondTimestamp

import logging
Expand Down Expand Up @@ -1454,8 +1454,8 @@ def __init__(self, db, metadata, dialect):
Column('locale', String(200)),
Column('osVersion', String(1000)),
Column('memory', String(100)),
Column('instructionSet', String(1000)),
Column('systemCapabilities', String(1000)),
Column('instructionSet', String(1000)),
Column('distribution', String(100)),
Column('distVersion', String(100)),
Column('headerArchitecture', String(10)),
Expand Down Expand Up @@ -1540,6 +1540,30 @@ def _buildIDMatchesRule(self, ruleBuildID, queryBuildID):
return True
return string_compare(queryBuildID, ruleBuildID)

def _memoryMatchesRule(self, ruleMemory, queryMemory):
"""Decides whether a memory value from the rules matches an incoming one.
If the ruleMemory is null, we match any queryMemory. If it's not
null, we must either match exactly, or match with a camparison
operator."""
if ruleMemory is None:
return True
return int_compare(queryMemory, ruleMemory)

def _csvMatchesRule(self, ruleString, queryString, substring=True):
"""Decides whether a column from a rule matches an incoming one.
Some columns in a rule may specify multiple values delimited by a
comma. Once split we do a full or substring match against the query
string. Because we support substring matches, there's no need
to support globbing as well."""
if ruleString is None:
return True
for part in ruleString.split(','):
if substring and part in queryString:
return True
elif part == queryString:
return True
return False

def _simpleBooleanMatchesSubRule(self, subRuleString, queryString, substring):
"""Performs the actual logical 'AND' operation on a rule as well as partial/full string matching
for each section of a rule.
Expand Down Expand Up @@ -1665,15 +1689,17 @@ def getRawMatches():
if not self._buildIDMatchesRule(rule['buildID'], updateQuery['buildID']):
self.log.debug("%s doesn't match %s", rule['buildID'], updateQuery['buildID'])
continue
if not self._memoryMatchesRule(rule['memory'], updateQuery.get("memory", "")):
self.log.debug("%s doesn't match %s", rule['memory'], updateQuery.get("memory"))
continue
# To help keep the rules table compact, multiple OS versions may be
# specified in a single rule. They are comma delimited, so we need to
# break them out and create clauses for each one.
if not self._simpleBooleanMatchesRule(rule['osVersion'], updateQuery['osVersion']):
self.log.debug("%s doesn't match %s", rule['osVersion'], updateQuery['osVersion'])
continue
# Same deal for system capabilities
if not self._simpleBooleanMatchesRule(rule['systemCapabilities'], updateQuery.get('systemCapabilities', ""), substring=False):
self.log.debug("%s doesn't match %s", rule['systemCapabilities'], updateQuery.get('systemCapabilities'))
if not self._csvMatchesRule(rule['instructionSet'], updateQuery.get('instructionSet', ""), substring=False):
self.log.debug("%s doesn't match %s", rule['instructionSet'], updateQuery.get('instructionSet'))
continue
# Locales may be a comma delimited rule too, exact matches only
if not self._localeMatchesRule(rule['locale'], updateQuery['locale']):
Expand Down
12 changes: 6 additions & 6 deletions auslib/test/admin/views/test_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ def testPost(self):
# Make some changes to a rule
ret = self._post('/rules/1', data=dict(backgroundRate=71, mapping='d', update_type='minor',
fallbackMapping="b", priority=73, data_version=1,
product='Firefox', channel='nightly', systemCapabilities="SSE"))
product='Firefox', channel='nightly', instructionSet="SSE"))
self.assertEquals(ret.status_code, 200, "Status Code: %d, Data: %s" % (ret.status_code, ret.data))
load = json.loads(ret.data)
self.assertEquals(load['new_data_version'], 2)
Expand All @@ -331,7 +331,7 @@ def testPost(self):
self.assertEquals(r[0]['mapping'], 'd')
self.assertEquals(r[0]['fallbackMapping'], 'b')
self.assertEquals(r[0]['backgroundRate'], 71)
self.assertEquals(r[0]['systemCapabilities'], "SSE")
self.assertEquals(r[0]['instructionSet'], "SSE")
self.assertEquals(r[0]['priority'], 73)
self.assertEquals(r[0]['data_version'], 2)
# And that we didn't modify other fields
Expand Down Expand Up @@ -992,8 +992,8 @@ def testGetScheduledChanges(self):
"version": "3.5", "buildTarget": "d", "backgroundRate": 100, "mapping": "b", "update_type": "minor",
"data_version": 1, "alias": None, "product": "a", "channel": "a", "buildID": None, "locale": None, "memory": None,
"osVersion": None, "distribution": None, "fallbackMapping": None, "distVersion": None, "headerArchitecture": None, "comment": None,
"instructionSet": None, "telemetry_product": None, "telemetry_channel": None, "telemetry_uptake": None, "systemCapabilities": None,
"change_type": "update", "signoffs": {}, "required_signoffs": {},
"instructionSet": None, "telemetry_product": None, "telemetry_channel": None, "telemetry_uptake": None,
"change_type": "update", "signoffs": {}, "required_signoffs": {}, "systemCapabilities": None,
},
{
"sc_id": 2, "when": 1500000, "scheduled_by": "bill", "complete": False, "sc_data_version": 1, "rule_id": None, "priority": 50,
Expand Down Expand Up @@ -1073,8 +1073,8 @@ def testGetScheduledChangesWithCompleted(self):
"version": "3.3", "buildTarget": "d", "backgroundRate": 0, "mapping": "c", "update_type": "minor",
"data_version": 1, "alias": None, "product": None, "channel": None, "buildID": None, "locale": None, "memory": None,
"osVersion": None, "distribution": None, "fallbackMapping": None, "distVersion": None, "headerArchitecture": None, "comment": None,
"instructionSet": None, "telemetry_product": None, "telemetry_channel": None, "telemetry_uptake": None, "systemCapabilities": None,
"change_type": "update", "signoffs": {}, "required_signoffs": {},
"instructionSet": None, "telemetry_product": None, "telemetry_channel": None, "telemetry_uptake": None,
"change_type": "update", "signoffs": {}, "required_signoffs": {}, "systemCapabilities": None,
},
{
"sc_id": 5, "when": 600000, "scheduled_by": "bill", "complete": False, "sc_data_version": 1, "rule_id": 4, "priority": None,
Expand Down

1 comment on commit 6d1c9d1

@bhearsum
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Taskcluster failures on this push are intermittents - retriggers worked fine.

Please sign in to comment.