Resource Opening compatibility with old test plans

Hi all,

We currently have a test step which refers to an instrument that is no longer in our Instrument Bench settings (or rather it was renamed into multiple different instruments) and the old name was serialized in some of our released test plans. Here is an image of it.

Previously the errors were being swallowed in 9.18.5 OpenTAP. However as we have upgraded to 9.22.3 OpenTAP version, the errors below now being thrown during Test Plan Load.

2023-12-01 12:15:10.3254 Error Operator Application : [TestEngineSession] XML Line 188: Missing 'DUTSwitch' used by 'SoftReset 1.0 Sec.DutSwitchComponent. Using 'DUTSwitch4' instead.'
2023-12-01 12:15:10.3254 Error Operator Application : [TestEngineSession] XML Line 1354: Missing 'DUTSwitch' used by 'SoftReset 1.5 Sec.DutSwitchComponent. Using 'DUTSwitch4' instead.'
2023-12-01 12:15:10.3254 Error Operator Application : [TestEngineSession] XML Line 5998: Missing 'DUTSwitch' used by 'SoftReset 0.5 Sec.DutSwitchComponent. Using 'DUTSwitch4' instead.'
2023-12-01 12:15:10.3254 Warn Operator Application : [TestEngineSession] Test Plan changed due to resources missing from Bench settings.
2023-12-01 12:15:10.3254 Warn Operator Application : [TestEngineSession] Please review these changes before saving or running the Test Plan.
2023-12-01 12:15:10.3254 Error .ctor method had an error
 Exception:XML Line 188: Missing 'DUTSwitch' used by 'SoftReset 1.0 Sec.DutSwitchComponent. Using 'DUTSwitch4' instead.'
XML Line 1354: Missing 'DUTSwitch' used by 'SoftReset 1.5 Sec.DutSwitchComponent. Using 'DUTSwitch4' instead.'
XML Line 5998: Missing 'DUTSwitch' used by 'SoftReset 0.5 Sec.DutSwitchComponent. Using 'DUTSwitch4' instead.'
 StackTrace:   at OpenTap.TestPlan.Load(Stream stream, String path, Boolean cacheXml, TapSerializer serializer, Boolean IgnoreLoadErrors)
   at OpenTap.TestPlan.Load(Stream stream, String path, Boolean cacheXml, TapSerializer serializer)
   at SHS.SMI.ITS.OpATapTestPlatform.AppTestPlan..ctor(String testPlanPath, List`1 resultListeners, List`1 metaDataForResultListener) in D:\Workspace\OpA_Main\ITSOperatorApplication\Source\ITS.OpATapTestPlatform\AppTestPlan.cs:line 41
2023-12-01 12:15:10.4009 Error Operator Application : TestPlan loading failed. XML Line 188: Missing 'DUTSwitch' used by 'SoftReset 1.0 Sec.DutSwitchComponent. Using 'DUTSwitch4' instead.'
XML Line 1354: Missing 'DUTSwitch' used by 'SoftReset 1.5 Sec.DutSwitchComponent. Using 'DUTSwitch4' instead.'
XML Line 5998: Missing 'DUTSwitch' used by 'SoftReset 0.5 Sec.DutSwitchComponent. Using 'DUTSwitch4' instead.'
2023-12-01 12:15:10.4009 Error Operator Application : 2008: Tap plan loading failed
XML Line 188: Missing 'DUTSwitch' used by 'SoftReset 1.0 Sec.DutSwitchComponent. Using 'DUTSwitch4' instead.'
XML Line 1354: Missing 'DUTSwitch' used by 'SoftReset 1.5 Sec.DutSwitchComponent. Using 'DUTSwitch4' instead.'
XML Line 5998: Missing 'DUTSwitch' used by 'SoftReset 0.5 Sec.DutSwitchComponent. Using 'DUTSwitch4' instead.' 

This is how it is implemented in our custom test steps.
image

Aside from adding it back to the instrument bench settings, is there another way we can keep backward compatibility with the released test plans without changing them? Maybe through the code? As re-releasing the test plans will take alot of effort in terms of testing.

Hi @antonio.quizon, ITapSerializerPlugin can be used for that kind of thing. Everything in OpenTAP is serialized/deserialized with it. Apart from adding new behavior, it can also be used to override existing behavior.

You can find an example here:

Hi @rolf_madsen,

Thanks again, for always helping out. With this approach, does it override the actual value in the test plan xml or does it just override the behaviour in the upper layer (something like a wrapper).
We need to know as we might not be able to modify the test plan, as there is a release process for them.

This approach modifies how the test plan file is read. In this specific case, it iterates through the XML document and modifies(patches) things so they can be correctly loaded afterwards.

Hi @rolf_madsen,

Some doubts on this approach. When do we call this Deserialize? Do we call it manually before loading the test plan? Or is it automatically triggered?

They are automatically discovered and triggered (according to priority) during serialization/deserialization.

Hi @rolf_madsen,

I am trying this approach, and am getting this error during TapSerializer.GetCurrentSerializer().Deserialize().

2023-12-05 10:23:13.2708 Error Deserialize method had an error
 Exception:Object reference not set to an instance of an object.
 StackTrace:   at SHS.SMI.ITS.OpATapTestPlatform.BreakingChangeFixupSerializer.Deserialize(XElement node, ITypeData t, Action`1 setter) in D:\Workspace\OpA_Main\ITSOperatorApplication\Source\ITS.OpATapTestPlatform\AppTestPlan.cs:line 488
2023-12-05 10:23:19.4209 Error Deserialize method had an error
 Exception:Object reference not set to an instance of an object.
 StackTrace:   at SHS.SMI.ITS.OpATapTestPlatform.BreakingChangeFixupSerializer.Deserialize(XElement node, ITypeData t, Action`1 setter) in D:\Workspace\OpA_Main\ITSOperatorApplication\Source\ITS.OpATapTestPlatform\AppTestPlan.cs:line 488
2023-12-05 10:23:59.0071 Error Deserialize method had an error
 Exception:Object reference not set to an instance of an object.
 StackTrace:   at SHS.SMI.ITS.OpATapTestPlatform.BreakingChangeFixupSerializer.Deserialize(XElement node, ITypeData t, Action`1 setter) in D:\Workspace\OpA_Main\ITSOperatorApplication\Source\ITS.OpATapTestPlatform\AppTestPlan.cs:line 488
2023-12-05 10:24:00.5687 Error .ctor method had an error
 Exception:Caught error while finishing serialization: Object reference not set to an instance of an object.
Caught error while finishing serialization: Object reference not set to an instance of an object.
Caught error while finishing serialization: Object reference not set to an instance of an object.
 StackTrace:   at OpenTap.TestPlan.Load(Stream stream, String path, Boolean cacheXml, TapSerializer serializer, Boolean IgnoreLoadErrors)
   at OpenTap.TestPlan.Load(Stream stream, String path, Boolean cacheXml, TapSerializer serializer)
   at SHS.SMI.ITS.OpATapTestPlatform.AppTestPlan..ctor(String testPlanPath, List`1 resultListeners, List`1 metaDataForResultListener) in D:\Workspace\OpA_Main\ITSOperatorApplication\Source\ITS.OpATapTestPlatform\AppTestPlan.cs:line 43
2023-12-05 10:24:00.6297 Error Operator Application : TestPlan loading failed. Caught error while finishing serialization: Object reference not set to an instance of an object.
Caught error while finishing serialization: Object reference not set to an instance of an object.
Caught error while finishing serialization: Object reference not set to an instance of an object.
2023-12-05 10:24:00.6297 Error Operator Application : [TestEngineSession] Caught error while finishing serialization: Object reference not set to an instance of an object.
2023-12-05 10:24:00.6297 Error Operator Application : [TestEngineSession] Caught error while finishing serialization: Object reference not set to an instance of an object.
2023-12-05 10:24:00.6297 Error Operator Application : [TestEngineSession] Caught error while finishing serialization: Object reference not set to an instance of an object.

I also want to understand more on the following:

  1. May I also understand what pre-scaling and post-scaling means?
  2. Why do we need to remove Parameter attributes during pre-scaling? Dont we need to add them back?
  3. Why do we need to add a new postscaling attribute, and replace the existing post scaling attribute?
  4. If my understanding is correct, the scaling is used mostly because of the conversion of milliseconds to seconds, and hence needs to be rescaled after changing. For our case, we only want to change the value of the instrument (as seen from previous post), I dont think we need to implement scaling?
  5. Also, just for my understanding, the expected return value for a successful deserialization is false?

Since you did not share the code, it is a bit hard to say why it fails. To answer your questions:

  1. Pre and post scaling are justand example of something you could do. What you are going to do is completely up to you. In this case the old property was in milliseconds and the new is seconds, so that needs to get adjusted for.
  2. It happens in two parses, first when it detects that we are loading a test plan, the scaling is inserted, then when the actual property is read the scaling will get applied. I am not totally sure why it needs to be done in this way.
  3. The post scaling is just added to the xml to have a place to store the data. It could also be stored in a dictionary. It is removed just to make sure that it wont be applied twice.
  4. Forget avout scaling :slight_smile: If you want to change value of the instrument it might be easiest to iterate all element values and just replace it with the string value you need.
  5. No, true is returned if you successfully deserialized the XML node. False is returned if you did not deserialise the object and other serializer plugins should be used. In this case our plugin just modified the XML code, it did not actually deserialize anything, so the regular logic should still be applied afterwards. Hence false is returned.

Hi @rolf_madsen,

Thanks for the help. I understand the scaling now, and I think it is not needed for now and I have removed it. Now we are just trying to iterate through the test plan and replace the element’s value with the correct instrument. If my understanding is correct, I should return false because I am simply replacing the xml and did not deserialize the object?

@antonio.quizon, thats correct.