blob: 6134afba6ff83561744c0928ffbef53467c225c4 [file] [log] [blame]
#!/usr/bin/python -u
# -*- coding: utf-8 -*-
#
# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# pylint: disable=E1101
import logging
import os
import unittest
import yaml
import factory_common # pylint: disable=W0611
from cros.factory import common_rule_functions #pylint: disable=W0611
from cros.factory.hwid.common import HWIDException
from cros.factory.hwid.database import Database
from cros.factory.hwid.encoder import Encode
from cros.factory.hwid.hwid_rule_functions import (
GetClassAttributesOnBOM, ComponentEq, ComponentIn,
SetComponent, SetImageId, GetDeviceInfo, GetVPDValue, ValidVPDValue,
CheckRegistrationCode, GetPhase)
from cros.factory.rule import (
Rule, Context, RuleException, SetContext, GetLogger)
from cros.factory.test import phase
from cros.factory.test.registration_codes import RegistrationCodeException
_TEST_DATA_PATH = os.path.join(os.path.dirname(__file__), 'testdata')
class HWIDRuleTest(unittest.TestCase):
def setUp(self):
self.database = Database.LoadFile(os.path.join(_TEST_DATA_PATH,
'test_db.yaml'))
self.results = [
yaml.dump(result) for result in yaml.load_all(open(os.path.join(
_TEST_DATA_PATH, 'test_probe_result.yaml')).read())]
bom = self.database.ProbeResultToBOM(self.results[0])
bom = self.database.UpdateComponentsOfBOM(bom, {
'keyboard': 'keyboard_us', 'dram': 'dram_0',
'display_panel': 'display_panel_0'})
self.hwid = Encode(self.database, bom)
self.device_info = {
'SKU': 1,
'has_cellular': False
}
self.vpd = {
'ro': {
'serial_number': 'foo',
'initial_locale': 'en-us'
},
'rw': {
'registration_code': 'buz'
}
}
self.context = Context(hwid=self.hwid, device_info=self.device_info,
vpd=self.vpd)
SetContext(self.context)
def testRule(self):
# Original binary string: 0000000000111010000011
# Original encoded string: CHROMEBOOK AA5A-Y6L
rule = Rule(name='foobar1',
when="GetDeviceInfo('SKU') == 1",
evaluate=[
"Assert(ComponentEq('cpu', 'cpu_5'))",
"Assert(ComponentEq('cellular', None))",
"SetComponent('dram', 'dram_1')"],
otherwise=None)
rule.Evaluate(self.context)
self.assertEquals(self.hwid.binary_string, r'0000000000111011000011')
self.assertEquals(self.hwid.encoded_string, r'CHROMEBOOK AA5Q-YM2')
rule = Rule(name='foobar2',
when="GetDeviceInfo('SKU') == 1",
evaluate=[
"Assert(ComponentEq('cpu', 'cpu_3'))"],
otherwise=None)
self.assertRaisesRegexp(
RuleException, r"ERROR: Assertion failed",
rule.Evaluate, self.context)
def testYAMLParsing(self):
rule = yaml.load("""
!rule
name: foobar1
when: GetDeviceInfo('SKU' == 1
evaluate:
- Assert(ComponentEq('cpu', 'cpu_5')
- Assert(ComponentEq('cellular', None))
- SetComponent('dram', 'dram_1')
""")
self.assertRaisesRegexp(
SyntaxError, r"unexpected EOF while parsing", rule.Validate)
rule = yaml.load("""
!rule
name: foobar1
when: GetDeviceInfo('SKU') == 1
evaluate:
- Assert(ComponentEq('cpu', 'cpu_5'))
- Assert(ComponentEq'cellular', None))
- SetComponent('dram', 'dram_1')
""")
self.assertRaisesRegexp(
SyntaxError, r"invalid syntax \(<string>, line 1\)", rule.Validate)
rule = yaml.load("""
!rule
name: foobar1
when: >
(GetDeviceInfo('SKU') == 1) and
(GetDeviceInfo('has_cellular') == False)
evaluate:
- Assert(ComponentEq('cpu', 'cpu_5'))
- Assert(ComponentEq('cellular', None))
- SetComponent('dram', 'dram_1')
""")
rule.Evaluate(self.context)
self.assertEquals(self.hwid.binary_string, r'0000000000111011000011')
self.assertEquals(self.hwid.encoded_string, r'CHROMEBOOK AA5Q-YM2')
rule = yaml.load("""
!rule
name: foobar2
when: ComponentEq('cpu', Re('cpu_.'))
evaluate: Assert(ComponentEq('cellular', None))
""")
self.assertEquals(None, rule.Evaluate(self.context))
rule = yaml.load("""
!rule
name: foobar2
when: ComponentEq('cpu', Re('cpu_.'))
evaluate: Assert(ComponentEq('cellular', 'cellular_0'))
""")
self.assertRaisesRegexp(
RuleException, r"ERROR: Assertion failed.",
rule.Evaluate, self.context)
rule = yaml.load("""
!rule
name: foobar2
when: GetDeviceInfo('SKU') == 1
evaluate: Assert(ComponentEq('cpu', 'cpu_3'))
""")
self.assertRaisesRegexp(
RuleException, r"ERROR: Assertion failed.",
rule.Evaluate, self.context)
rule = yaml.load("""
!rule
name: foobar3
when: Re('en-.*').Matches(GetVPDValue('ro', 'initial_locale'))
evaluate: Assert(ComponentEq('cpu', 'cpu_3'))
""")
self.assertRaisesRegexp(
RuleException, r"ERROR: Assertion failed.",
rule.Evaluate, self.context)
def testGetClassAttributesOnBOM(self):
cpu_attrs = GetClassAttributesOnBOM(self.hwid, 'cpu')
self.assertEquals(['cpu_5'], cpu_attrs)
storage_attrs = GetClassAttributesOnBOM(self.hwid, 'storage')
self.assertEquals(['storage_0', 'SSD', '16G'], storage_attrs)
self.assertEquals(None, GetClassAttributesOnBOM(self.hwid, 'foo'))
self.assertEquals("ERROR: Invalid component class: 'foo'",
GetLogger().error[0].message)
def testComponentEq(self):
self.assertTrue(ComponentEq('cpu', 'cpu_5'))
self.assertTrue(
ComponentEq('storage', ['SSD', '16G']))
self.assertFalse(ComponentEq('cpu', 'cpu_3'))
self.assertFalse(
ComponentEq('storage', ['SSD', '32G']))
def testComponentIn(self):
self.assertTrue(
ComponentIn('cpu', ['cpu_3', 'cpu_4', 'cpu_5']))
self.assertTrue(
ComponentIn('storage', ['16G', '32G']))
self.assertFalse(
ComponentIn('cpu', ['cpu_3', 'cpu_4']))
def testSetComponent(self):
SetComponent('cpu', 'cpu_3')
self.assertEquals(
'cpu_3', self.context.hwid.bom.components['cpu'][0].component_name)
self.assertEquals(
3, self.context.hwid.bom.encoded_fields['cpu'])
self.assertEquals('0000000000111010010001', self.hwid.binary_string)
self.assertEquals('CHROMEBOOK AA5E-IVL', self.hwid.encoded_string)
SetComponent('cellular', 'cellular_0')
self.assertEquals(
'cellular_0',
self.context.hwid.bom.components['cellular'][0].component_name)
self.assertEquals(
1, self.context.hwid.bom.encoded_fields['cellular'])
self.assertEquals('0000000000111110010001', self.hwid.binary_string)
self.assertEquals('CHROMEBOOK AA7E-IWF', self.hwid.encoded_string)
def testSetImageId(self):
SetImageId(1)
self.assertEquals('0000100000111010000011', self.hwid.binary_string)
self.assertEquals('CHROMEBOOK BA5A-YI3', self.hwid.encoded_string)
SetImageId(2)
self.assertEquals('0001000000111010000011', self.hwid.binary_string)
self.assertEquals('CHROMEBOOK C2H-I3Q-A6Q', self.hwid.encoded_string)
self.assertRaisesRegexp(
HWIDException, r'Invalid image id: 7', SetImageId, 7)
def testValidVPDValue(self):
mock_vpd = {
'ro': {
'initial_locale': 'en-US',
'initial_timezone': 'America/Los_Angeles',
'keyboard_layout': 'xkb:us::eng',
'serial_number': 'foobar'
}
}
SetContext(Context(vpd=mock_vpd))
self.assertEquals(True, ValidVPDValue('ro', 'initial_locale'))
self.assertEquals(True, ValidVPDValue('ro', 'initial_timezone'))
self.assertEquals(True, ValidVPDValue('ro', 'keyboard_layout'))
self.assertEquals(True, ValidVPDValue('ro', 'serial_number'))
mock_vpd = {
'ro':{
'initial_locale': 'foo'
}
}
SetContext(Context(vpd=mock_vpd))
self.assertFalse(ValidVPDValue('ro', 'initial_locale'))
self.assertEquals("ERROR: Invalid VPD value 'foo' of 'initial_locale'",
GetLogger().error[0].message)
mock_vpd = {
'ro':{
'initial_timezone': 'foo'
}
}
SetContext(Context(vpd=mock_vpd))
self.assertFalse(ValidVPDValue('ro', 'initial_timezone'))
self.assertEquals("ERROR: Invalid VPD value 'foo' of 'initial_timezone'",
GetLogger().error[0].message)
mock_vpd = {
'ro':{
'keyboard_layout': 'foo'
}
}
SetContext(Context(vpd=mock_vpd))
self.assertFalse(ValidVPDValue('ro', 'keyboard_layout'))
self.assertEquals("ERROR: Invalid VPD value 'foo' of 'keyboard_layout'",
GetLogger().error[0].message)
def testCheckRegistrationCode_Legacy(self):
mock_gbind_attribute = ('3333333333333333333333333333333333333'
'3333333333333333333333333332dbecc73')
mock_ubind_attribute = ('3232323232323232323232323232323232323'
'23232323232323232323232323256850612')
self.assertEquals(None, CheckRegistrationCode(mock_gbind_attribute))
self.assertEquals(None, CheckRegistrationCode(mock_ubind_attribute))
mock_gbind_attribute = 'foo'
self.assertRaisesRegexp(
RegistrationCodeException, r"Invalid registration code 'foo'",
CheckRegistrationCode, mock_gbind_attribute)
def testCheckRegistrationCode(self):
mock_ubind_attribute = (
'=CjAKIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fEAEaCmNocm9tZWJvb2sQg'
'dSQ-AI=')
self.assertEquals(None, CheckRegistrationCode(mock_ubind_attribute))
self.assertEquals(None, CheckRegistrationCode(mock_ubind_attribute,
type='unique'))
self.assertRaisesRegexp(
RegistrationCodeException,
"expected type 'GROUP_CODE' but got 'UNIQUE_CODE'",
CheckRegistrationCode, mock_ubind_attribute, type='group')
mock_gbind_attribute = (
'=CjAKIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fEAAaCmNocm9tZWJvb2sQh'
'OfLlA8=')
self.assertEquals(None, CheckRegistrationCode(mock_gbind_attribute))
self.assertEquals(None, CheckRegistrationCode(mock_gbind_attribute,
type='group'))
self.assertRaisesRegexp(
RegistrationCodeException,
"expected type 'UNIQUE_CODE' but got 'GROUP_CODE'",
CheckRegistrationCode, mock_gbind_attribute, type='unique')
self.assertRaisesRegexp(
RegistrationCodeException,
"expected device 'chromebook' but got 'foobar'",
CheckRegistrationCode,
'=CiwKIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fEAEaBmZvb2JhchC7i6PaD'
'w==')
def testGetDeviceInfo(self):
self.assertEquals(1, GetDeviceInfo('SKU'))
self.assertEquals(
False, GetDeviceInfo('has_cellular'))
def testGetDeviceInfoDefault(self):
self.assertEquals(1, GetDeviceInfo('SKU'))
self.assertEquals(
'Default', GetDeviceInfo('has_something', 'Default'))
def testGetVPDValue(self):
self.assertEquals(
'foo', GetVPDValue('ro', 'serial_number'))
self.assertEquals(
'buz', GetVPDValue('rw', 'registration_code'))
def testGetPhase(self):
# Should be 'PVT' when no build phase is set.
self.assertEquals('PVT', GetPhase())
phase._current_phase = phase.PROTO
self.assertEquals('PROTO', GetPhase())
phase._current_phase = phase.PVT_DOGFOOD
self.assertEquals('PVT_DOGFOOD', GetPhase())
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
unittest.main()