Release note: sf bug 2174: --layer option shows errors when bld.inf missing in another layer fix
authorDean Draper <dean.draper@nokia.com>
Fri, 30 Apr 2010 10:19:33 +0100
branchfix
changeset 491 f60c4282816c
parent 490 b60bdff41580
child 496 50b7c0278040
child 511 7581d432643a
Release note: sf bug 2174: --layer option shows errors when bld.inf missing in another layer
sbsv2/raptor/RELEASE-NOTES.html
sbsv2/raptor/python/raptor_xml.py
sbsv2/raptor/test/metadata/system/system_definition_multi_layers.xml
sbsv2/raptor/test/unit_suite/raptor_xml_unit.py
--- a/sbsv2/raptor/RELEASE-NOTES.html	Tue Apr 20 13:41:38 2010 +0100
+++ b/sbsv2/raptor/RELEASE-NOTES.html	Fri Apr 30 10:19:33 2010 +0100
@@ -12,6 +12,7 @@
 <ul>
 
 <li><a href="http://developer.symbian.org/bugs/show_bug.cgi?id=2297"> SF Bug 2297 </a> Python exception in raptor_meta.py when processing bld.inf file </li>
+<li><a href="http://developer.symbian.org/bugs/show_bug.cgi?id=2174"> SF Bug 2174 </a> -- layer option shows errors when bld.inf missing in another layer </li>
 
 </ul>
 
--- a/sbsv2/raptor/python/raptor_xml.py	Tue Apr 20 13:41:38 2010 +0100
+++ b/sbsv2/raptor/python/raptor_xml.py	Fri Apr 30 10:19:33 2010 +0100
@@ -11,7 +11,7 @@
 #
 # Contributors:
 #
-# Description: 
+# Description:
 # raptor_xml module
 #
 
@@ -67,15 +67,15 @@
 	objects = []
 
 	fileVersion = build.getAttribute("xsi:schemaLocation")
-	
+
 	# ignore the file it matches the "invalid" schema
 	if fileVersion.endswith(xsdIgnore):
 		return objects
-		
+
 	# check that the file matches the expected schema
 	if not fileVersion.endswith(xsdVersion):
 		Raptor.Warn("file '%s' uses schema '%s' which does not end with the expected version '%s'", filename, fileVersion, xsdVersion)
-		
+
 	# create a Data Model object from each sub-element
 	for child in build.childNodes:
 		if child.namespaceURI == namespace \
@@ -147,21 +147,21 @@
 	def __init__(self, aBldInfFile, aLayerName, aContainerNames, aSystemDefinitionFile, aSystemDefinitionBase, aSystemDefinitionVersion):
 		generic_path.Path.__init__(self, aBldInfFile.Absolute().path)
 		self.__ContainerNames = aContainerNames
-		self.__LayerName = aLayerName
+		self.__LayerName = aLayerName
 		self.__SystemDefinitionFile = aSystemDefinitionFile
-		self.__SystemDefinitionBase = aSystemDefinitionBase
-		self.__SystemDefinitionVersion = aSystemDefinitionVersion
+		self.__SystemDefinitionBase = aSystemDefinitionBase
+		self.__SystemDefinitionVersion = aSystemDefinitionVersion
 
 	def GetSystemDefinitionFile(self):
 		return self.__SystemDefinitionFile
 
 	def GetSystemDefinitionBase(self):
 		return self.__SystemDefinitionBase
-
-	def GetSystemDefinitionVersion(self):
-		return self.__SystemDefinitionVersion
-
-	def GetLayerName(self):
+
+	def GetSystemDefinitionVersion(self):
+		return self.__SystemDefinitionVersion
+
+	def GetLayerName(self):
 		return self.__LayerName
 
 	def GetContainerName(self, aContainerType):
@@ -177,12 +177,13 @@
 		self.__Logger = aLogger
 		self.__SystemDefinitionFile = aSystemDefinitionFile.GetLocalString()
 		self.__SystemDefinitionBase = aSystemDefinitionBase.GetLocalString()
-		self.__Version = {'MAJOR':0,'MID':0,'MINOR':0}
-		self.__IdAttribute = "name"
+		self.__Version = {'MAJOR':0,'MID':0,'MINOR':0}
+		self.__IdAttribute = "name"
 		self.__ComponentRoot = ""
 		self.__TotalComponents = 0
 		self.__LayerList = []
 		self.__LayerDetails = {}
+		self.__MissingBldInfs = {}
 
 		self.__DOM = None
 		self.__SystemDefinitionElement = None
@@ -208,10 +209,16 @@
 		return self.__LayerDetails[aLayer]
 
 	def IsLayerBuildable(self, aLayer):
+		if aLayer in self.__MissingBldInfs:
+			for missingbldinf in self.__MissingBldInfs[aLayer]:
+				self.__Logger.Error("System Definition layer \"%s\" from system definition file \"%s\" " + \
+								    "refers to non existent bld.inf file %s", aLayer, self.__SystemDefinitionFile, missingbldinf)
+
 		if len(self.GetLayerComponents(aLayer)):
 			return True
 		return False
 
+
 	def GetAllComponents(self):
 		components = []
 
@@ -268,33 +275,33 @@
 
 		if self.__Version['MAJOR'] == 1 and self.__Version['MID'] > 2:
 			self.__ComponentRoot = self.__SystemDefinitionBase
-		elif self.__Version['MAJOR'] == 2 or self.__Version['MAJOR'] == 3:
-			# 2.0.x and 3.0.0 formats support SOURCEROOT or SRCROOT as an environment specified base - we respect this, unless
-			# explicitly overridden on the command line
-			if os.environ.has_key('SRCROOT'):
-				self.__ComponentRoot = generic_path.Path(os.environ['SRCROOT'])
-			elif os.environ.has_key('SOURCEROOT'):
+		elif self.__Version['MAJOR'] == 2 or self.__Version['MAJOR'] == 3:
+			# 2.0.x and 3.0.0 formats support SOURCEROOT or SRCROOT as an environment specified base - we respect this, unless
+			# explicitly overridden on the command line
+			if os.environ.has_key('SRCROOT'):
+				self.__ComponentRoot = generic_path.Path(os.environ['SRCROOT'])
+			elif os.environ.has_key('SOURCEROOT'):
 				self.__ComponentRoot = generic_path.Path(os.environ['SOURCEROOT'])
-				
-			if self.__SystemDefinitionBase and self.__SystemDefinitionBase != ".":
-				self.__ComponentRoot = self.__SystemDefinitionBase
-				if os.environ.has_key('SRCROOT'):
-					self.__Logger.Info("Command line specified System Definition file base \'%s\' overriding environment SRCROOT \'%s\'", self.__SystemDefinitionBase, os.environ['SRCROOT'])
-				elif os.environ.has_key('SOURCEROOT'):
-					self.__Logger.Info("Command line specified System Definition file base \'%s\' overriding environment SOURCEROOT \'%s\'", self.__SystemDefinitionBase, os.environ['SOURCEROOT'])
+
+			if self.__SystemDefinitionBase and self.__SystemDefinitionBase != ".":
+				self.__ComponentRoot = self.__SystemDefinitionBase
+				if os.environ.has_key('SRCROOT'):
+					self.__Logger.Info("Command line specified System Definition file base \'%s\' overriding environment SRCROOT \'%s\'", self.__SystemDefinitionBase, os.environ['SRCROOT'])
+				elif os.environ.has_key('SOURCEROOT'):
+					self.__Logger.Info("Command line specified System Definition file base \'%s\' overriding environment SOURCEROOT \'%s\'", self.__SystemDefinitionBase, os.environ['SOURCEROOT'])
 		else:
 			self.__Logger.Error("Cannot process schema version %s of file %s", version.string, self.__SystemDefinitionFile)
 			return False
-
-		if self.__Version['MAJOR'] >= 3:
-			# id is the unique identifier for 3.0 and later schema
-			self.__IdAttribute = "id"
+
+		if self.__Version['MAJOR'] >= 3:
+			# id is the unique identifier for 3.0 and later schema
+			self.__IdAttribute = "id"
 
 		return True
 
 	def __Parse(self):
 		# For 2.0 and earlier: find the <systemModel> element (there can be 0 or 1) and search any <layer> elements for <unit> elements with "bldFile" attributes
-		# the <layer> context of captured "bldFile" attributes is recorded as we go
+		# the <layer> context of captured "bldFile" attributes is recorded as we go
 		# For 3.0 and later, process any architectural topmost element, use the topmost element with an id as the "layer"
 		for child in self.__SystemDefinitionElement.childNodes:
 			if child.localName in ["systemModel", "layer", "package", "collection", "component"]:
@@ -303,20 +310,20 @@
 	def __CreateComponent(self, aBldInfFile, aUnitElement):
 		# take a resolved bld.inf file and associated <unit/> element and returns a populated Component object
 		containers = {}
-		self.__GetElementContainers(aUnitElement, containers)
+		self.__GetElementContainers(aUnitElement, containers)
 		layer = self.__GetEffectiveLayer(aUnitElement)
 		component = SystemModelComponent(aBldInfFile, layer, containers, self.__SystemDefinitionFile, self.__SystemDefinitionBase, self.__Version)
 
 		return component
-
-	def __GetEffectiveLayer(self, aElement):
-		#' return the ID of the topmost item which has an ID. For 1.x and 2.x, this will always be layer, for 3.x, it will be the topmost ID'd element in the file
-		# never call this on the root element
-		if aElement.parentNode.hasAttribute(self.__IdAttribute):
-			return self.__GetEffectiveLayer(aElement.parentNode)
-		elif aElement.hasAttribute(self.__IdAttribute):
-			return aElement.getAttribute(self.__IdAttribute)
-		return ""
+
+	def __GetEffectiveLayer(self, aElement):
+		#' return the ID of the topmost item which has an ID. For 1.x and 2.x, this will always be layer, for 3.x, it will be the topmost ID'd element in the file
+		# never call this on the root element
+		if aElement.parentNode.hasAttribute(self.__IdAttribute):
+			return self.__GetEffectiveLayer(aElement.parentNode)
+		elif aElement.hasAttribute(self.__IdAttribute):
+			return aElement.getAttribute(self.__IdAttribute)
+		return ""
 
 	def __GetElementContainers(self, aElement, aContainers):
 		# take a <unit/> element and creates a type->name dictionary of all of its parent containers
@@ -333,7 +340,7 @@
 	def __ProcessSystemModelElement(self, aElement):
 		"""Search for XML <unit/> elements with 'bldFile' attributes and resolve concrete bld.inf locations
 		with an appreciation of different schema versions."""
-
+
 		# The effective "layer" is the item whose parent does not have an id (or name in 2.x and earlier)
 		if not aElement.parentNode.hasAttribute(self.__IdAttribute) :
 			currentLayer = aElement.getAttribute(self.__IdAttribute)
@@ -368,19 +375,26 @@
 
 				group = generic_path.Path(bldFileValue)
 
-				if self.__Version['MAJOR'] < 3:
-					# absolute paths are not changed by root var in 1.x and 2.x
+				if self.__Version['MAJOR'] < 3:
+					# absolute paths are not changed by root var in 1.x and 2.x
 					if not group.isAbsolute() and bldInfRoot:
-						group = generic_path.Join(bldInfRoot, group)
-				else:
-					# only absolute paths are changed by root var in 3.x
-					if group.isAbsolute() and bldInfRoot:
-						group = generic_path.Join(bldInfRoot, group)
+						group = generic_path.Join(bldInfRoot, group)
+				else:
+					# only absolute paths are changed by root var in 3.x
+					if group.isAbsolute() and bldInfRoot:
+						group = generic_path.Join(bldInfRoot, group)
 
 				bldinf = generic_path.Join(group, "bld.inf").FindCaseless()
 
 				if bldinf == None:
-					self.__Logger.Error("No bld.inf found at %s in %s", group.GetLocalString(), self.__SystemDefinitionFile)
+					# recording layers containing non existent bld.infs
+					bldinfname = group.GetLocalString()
+					bldinfname = bldinfname + 'bld.inf'
+					layer = self.__GetEffectiveLayer(aElement)
+					if not layer in self.__MissingBldInfs:
+						self.__MissingBldInfs[layer]=[]
+					self.__MissingBldInfs[layer].append(bldinfname)
+
 				else:
 					component = self.__CreateComponent(bldinf, aElement)
 					layer = component.GetLayerName()
--- a/sbsv2/raptor/test/metadata/system/system_definition_multi_layers.xml	Tue Apr 20 13:41:38 2010 +0100
+++ b/sbsv2/raptor/test/metadata/system/system_definition_multi_layers.xml	Fri Apr 30 10:19:33 2010 +0100
@@ -34,5 +34,14 @@
 		</layer>
 	    <layer name="Fifth Layer">
 		</layer>
+		<!--layer name="Sixth layer" deliberately omitted -->
+	    <layer name="Seventh Layer">
+			<component name="simple_stringtable">
+				<unit bldFile="test/smoke_suite/test_resources/simple_plugin" root="SBS_HOME" mrp="simple_plugin/test.mrp"/>
+			</component>
+			<component name="does_not_exist">
+				<unit bldFile="test/smoke_suite/test_resources/does_not_exist" root="SBS_HOME" mrp="does_not_exist/test.mrp"/>
+			</component>
+		</layer>
 	</systemModel>
 </SystemDefinition>
--- a/sbsv2/raptor/test/unit_suite/raptor_xml_unit.py	Tue Apr 20 13:41:38 2010 +0100
+++ b/sbsv2/raptor/test/unit_suite/raptor_xml_unit.py	Fri Apr 30 10:19:33 2010 +0100
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+# Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
 # All rights reserved.
 # This component and the accompanying materials are made available
 # under the terms of the License "Eclipse Public License v1.0"
@@ -17,15 +17,34 @@
 #
 
 import os
+import generic_path
 import raptor
-import generic_path
 import raptor_xml
 import unittest
 
 class TestRaptorXML(unittest.TestCase):
+		
+	class Logger(object):
+		# Basic custom logger class to store errors (and only errors) for test checks
+
+		def __init__(self):	
+			self.errors = []
+					
+		def Error(self, format, *extras, **attributes):
+			self.errors.append(format % extras)
+
+		def Info(self, format, *extras, **attributes):
+			return
+			
+		def InfoDiscovery(self, object_type, count):
+			return
+		
+		def Clear(self):
+			del self.errors[:]
+			
 	
 	def setUp(self):
-		self.__logger = raptor.Raptor()
+		self.__logger = TestRaptorXML.Logger()
 		self.__nullSysDefRoot = generic_path.Path("smoke_suite/test_resources")
 		self.__sysDefRoot = generic_path.Join(os.environ[raptor.env],"test/smoke_suite/test_resources")
 		self.__sysDefFileRoot = generic_path.Join(os.environ[raptor.env], "test/metadata/system")
@@ -64,8 +83,11 @@
 		systemModel = raptor_xml.SystemModel(self.__logger, generic_path.Join(self.__sysDefFileRoot, "system_definition_3.0.0.xml"), self.__sysDefRoot)
 		self.__compareFileLists([], systemModel.GetAllComponents())
 				
-		
+		self.__logger.Clear()
 		systemModel = raptor_xml.SystemModel(self.__logger, generic_path.Join(self.__sysDefFileRoot, "system_definition_multi_layers.xml"), self.__sysDefRoot)
+		self.assertTrue(len(self.__logger.errors) == 0)
+
+		# Confirm components returned from layers are correct
 
 		expectedBldInfs = [ generic_path.Join(self.__sysDefRoot, "simple/bld.inf"),\
 							generic_path.Join(self.__sysDefRoot, "simple_dll/bld.inf"),\
@@ -74,7 +96,8 @@
 						    generic_path.Join(self.__sysDefRoot, "simple_implib/bld.inf"),\
 						    generic_path.Join(self.__sysDefRoot, "simple_lib/bld.inf"),\
 						    generic_path.Join(self.__sysDefRoot, "simple_stringtable/bld.inf"),\
-						    generic_path.Join(self.__sysDefRoot, "simple_test/bld.inf")]
+						    generic_path.Join(self.__sysDefRoot, "simple_test/bld.inf"),\
+						    generic_path.Join(self.__sysDefRoot, "simple_plugin/bld.inf")]
 		self.__compareFileLists(expectedBldInfs, systemModel.GetAllComponents())
 	
 		expectedBldInfs = [ generic_path.Join(self.__sysDefRoot, "simple_export/bld.inf"),\
@@ -85,6 +108,23 @@
 				
 		self.__compareFileLists([], systemModel.GetLayerComponents("Sixth Layer"))
 		
+		# Check that the overall "buildability" of layers is returned correctly
+		# Note that a layer is still buildable if some bld.infs in it are missing as long as at least 1 exists
+		# However, errors should always be generated for missing bld.infs when a layer is checked
+		
+		self.assertTrue(systemModel.IsLayerBuildable("First Layer"))		
+		self.assertFalse(systemModel.IsLayerBuildable("Sixth Layer"))
+		
+		self.__logger.Clear()
+		self.assertTrue(systemModel.IsLayerBuildable("Seventh Layer"))
+		self.assertTrue(len(self.__logger.errors) == 1)
+		sbsHome = os.environ["SBS_HOME"]
+		sysDefPath = sbsHome + "/test/metadata/system/system_definition_multi_layers.xml"
+		sysDefPath = sysDefPath.replace("\\","/")
+		bldInfPath = sbsHome + "/test/smoke_suite/test_resources/does_not_existbld.inf"
+		bldInfPath = bldInfPath.replace("\\","/")
+		self.assertEquals(self.__logger.errors[0],
+		  ("System Definition layer \"Seventh Layer\" from system definition file \"%s\" refers to non existent bld.inf file %s" % (sysDefPath, bldInfPath)))
 				
 		# Probably redundant, but return local environment (at least its dictionary) to pre-test state
 		os.environ["SOURCEROOT"] = sourceroot