text: # Copyright 2015 The Chromium Authors. All rights reserved.
  # Use of this source code is governed by a BSD-style license that can be
  # found in the LICENSE file.
  import collections
  import itertools
  import os
  import unittest
  
  from telemetry.testing import fakes
  
  from gpu_tests import fake_win_amd_gpu_info
  from gpu_tests import path_util
  from gpu_tests import test_expectations
  from gpu_tests import webgl_conformance_expectations
  from gpu_tests import webgl_conformance_integration_test
  from gpu_tests import webgl2_conformance_expectations
  
  class FakeWindowsPlatform(fakes.FakePlatform):
    @property
    def is_host_platform(self):
      return True
  
    def GetDeviceTypeName(self):
      return 'Desktop'
  
    def GetArchName(self):
      return 'x86_64'
  
    def GetOSName(self):
      return 'win'
  
    def GetOSVersionName(self):
      return 'win8'
  
    def GetOSVersionDetailString(self):
      # Not sure whether this is accurate.
      return 'Windows 8.1'
  
  
  class WebGLTestInfo(object):
    def __init__(self, url):
      self.name = ('WebglConformance_%s' %
                   url.replace('/', '_').replace('-', '_').
                   replace('\\', '_').rpartition('.')[0].replace('.', '_'))
      self.url = 'file://' + url
  
  Conditions = collections.\
    namedtuple('Conditions', ['non_gpu', 'vendors', 'devices'])
  
  class WebGLConformanceExpectationsTest(unittest.TestCase):
    def testGlslConstructVecMatIndexExpectationOnWin(self):
      possible_browser = fakes.FakePossibleBrowser()
      browser = possible_browser.Create(None)
      browser.platform = FakeWindowsPlatform()
      browser.returned_system_info = fakes.FakeSystemInfo(
        gpu_dict=fake_win_amd_gpu_info.FAKE_GPU_INFO)
      expectations = webgl_conformance_expectations.\
                     WebGLConformanceExpectations(
                       os.path.join(
                         path_util.GetChromiumSrcDir(),
                         'third_party', 'webgl', 'src', 'sdk', 'tests'))
      test_info = WebGLTestInfo(
        'conformance/glsl/constructors/glsl-construct-vec-mat-index.html')
      expectation = expectations.GetExpectationForTest(
        browser, test_info.url, test_info.name)
      # TODO(kbr): change this expectation back to "flaky". crbug.com/534697
      self.assertEquals(expectation, 'fail')
  
    def testWebGLExpectationsHaveNoCollisions(self):
      conformance = webgl_conformance_expectations.\
        WebGLConformanceExpectations(
          webgl_conformance_integration_test.conformance_path)
  
      self.checkConformanceHasNoCollisions(conformance)
  
    def testWebGL2ExpectationsHaveNoCollisions(self):
      conformance = webgl2_conformance_expectations.\
        WebGL2ConformanceExpectations(
          webgl_conformance_integration_test.conformance_path)
  
      self.checkConformanceHasNoCollisions(conformance)
  
    def checkConformanceHasNoCollisions(self, conformance):
      # Checks that no two expectations for the same page can match the
      # same configuration (wildcards expectations are ok though).
      # See webgl2_conformance_expectations.py that contains commented out
      # conflicting expectations that can be used to test this function.
      expectations = conformance.GetAllNonWildcardExpectations()
  
      # Extract the conditions of the expectations as a tuple of sets, one
      # set for each aspect (OS, GPU...) of the expectations.
      conditions_by_pattern = dict()
      for e in expectations:
        conditions_by_pattern[e.pattern] = []
  
      for e in expectations:
        # Specifiying 'mac' or 'win' is equivalent to specifying all the
        # OS's versions
        os_conditions = e.os_conditions
        if 'win' in os_conditions:
          os_conditions += test_expectations.WIN_CONDITIONS
        if 'mac' in os_conditions:
          os_conditions += test_expectations.MAC_CONDITIONS
  
        conditions_by_pattern[e.pattern].append(Conditions(
          (
            set(e.os_conditions),
            set(e.browser_conditions),
            set(e.asan_conditions),
            set(e.cmd_decoder_conditions),
            set(e.angle_conditions),
          ),
          set(e.gpu_conditions),
          set(e.device_id_conditions),
        ))
  
      for (pattern, conditions) in conditions_by_pattern.iteritems():
        for (c1, c2) in itertools.combinations(conditions, 2):
          # Two conditions for the same page conflict iff we can find a
          # configuration satisfying both conditions, that is iff for each
          # aspect, one of the following is true:
          #  - One of the conditions doesn't specify a requirement for that
          # aspect, which means we can get a value valid for the other condition
          #  - Both conditions have requirements but they intersect
          non_gpu_conflicts = all(
            [len(aspect1.intersection(aspect2)) != 0 or \
              len(aspect1) == 0 or len(aspect2) == 0 \
              for (aspect1, aspect2) in zip(c1.non_gpu, c2.non_gpu)])
  
          # A GPU configuration matches an expectation if it matches either the
          # GPU vendor condition or the GPU device condition. This means that
          # we can have a conflicting configuration if one of the following
          # is true:
          # - There are no conditions
          # - The GPU vendors or the GPU devices intersect
          # - There is a device of a condition that matches the vendors of
          # the other condition
          gpu_conflicts = \
            len(c1.vendors) + len(c1.devices) == 0 or \
            len(c2.vendors) + len(c2.devices) == 0 or \
            len(c1.vendors.intersection(c2.vendors)) != 0 or \
            len(c1.devices.intersection(c2.devices)) != 0 or \
            any([vendor in c1.vendors for (vendor, _) in c2.devices]) or \
            any([vendor in c2.vendors for (vendor, _) in c1.devices])
  
          conflicts = non_gpu_conflicts and gpu_conflicts
  
          if conflicts:
            print "WARNING: Found a conflict for", pattern, " :"
            print "  ", c1
            print "  ", c2
  
            print "  Type:" + (" (non-gpu)" if non_gpu_conflicts else "") + \
              (" (gpu)" if gpu_conflicts else "")
          self.assertEquals(conflicts, False)
  