Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Fix for Can't activate two sip RA entities. #28
This is a proposed fix for issue/27.
Class loading influence might be a separate thing, and it can cover the root cause of SIP RA issue. If SIP RA entities are created from different class loaders, then the issue may not appear.
SipFactory is a singleton and it keeps track of existing SipStack instances created by SipFactory, basically the same stack instance is returned in case:
SipFactory first relies on javax.sip.IP_ADDRESS, then on javax.sip.STACK_NAME.
Since SipResourceAdaptor provided javax.sip.IP_ADDRESS, then the same stack was returned by SipFactory, but later on in raActive(), new provider and listener were created and added to existing stack (which already had provider/listener set).
Now, different class loaders implies different singletons (SipFactory) created. The other singleton knows nothing about first stack crated, thus it will create a new stack.
The fix just removes IP_ADDRESS from properties passed to SipFactory. Still it allows to create a listening point passed to RA configuration.
There is a unit test provided to verify the fix.
Focused and good solution. Test is good but introduces lots of new mocks libs,which im not sure are worthy
The question is, to use mock libraries or not to use.
I guess it is a subjective. Looking purely from the perspective of a single case, it may be enough to provide DummyTracer, DummyResourceAdaptorContext, etc.
However I see some benefits of using mock libraries long term and uniformly across the project:
a) sipStack is a private field, therefore one would need to use some reflection API to get it, and later on to get listening points associated with the stack. This operation is facilitated by powermock toolkit (Whitebox class).
The other solution would be to expose ClusteredSipStack from SIP RA, but is this ok? I suppose there are reasons not to expose it (if opposite, then initially it would be already accessible :)).
Now, exposing getClusteredStack() brings another question. Should we, in general, have some interface (or rather interfaces hierarchy) which will expose operations only for test purposes, (some UnitTestContext / SipRAUnitTestContext etc.) ?
b) Having an interface with 20+ operations, shall I implement all these ? ("DummyTracer approach") or be lazy and provide only what is necessary? (mock one operation needed from the perspective of a given test).
c) If in need of different behaviour for another test, shall I subclass DummyTracer or to prepare another mock answer? How reusable mocks should be?
I prefer to have some generic toolkit, but again, this is my personal view.
Is there some generic approach to be applied in the project? So I could align with that or to stay with mockito+powermock ?
As you can see, the existing tests are more focus on testing specific "wrapper" logic of different wrapper classes, as this SIPRA component is basically a wrapper of JAIN-SIP stack. For this simple wrapper UnitTest code we have not required complex mocking/stubbing techniques yet.
Having said that, I really prefer mocking versus stubbing. Again, there is no mocking approach for this particular component. For the rest of Restcomm projects we have used "mockito" lib before, so that certainly align with our current approach.
Since we are focusing the PR discussion on testing, rather than actual implementation, I would say this is ok for me. I'll wait for @SergeyLee comments to finally merge