I understand that in every #Test method, I should use a new instance of SoftAssert.
However, is there any way to flush or reuse the already existing one? Or how do I free up memory after every test case?
If I have 1000 test cases, isn't creating 1000 instances of SoftAssert inefficient? Also, it is possible that when the system is executing 1000th test case, 999 instances of SoftAssert will be sitting in the memory doing nothing, correct?
So in essence, what is the best way to use SoftAssert?
Take a look at this question
Java Object Reuse.
I think when you talk about 1000 instances, you should not care about this.
Also, SoftAssert seems not designed to be reusable, there are no clear/flush methods
https://javadoc.io/doc/org.testng/testng/latest/org/testng/asserts/SoftAssert.html.
Related
I am creating several ByteBuddy classes (using DynamicTypeBuilder) and loading them. The creation of these classes and the loading of them happens on a single thread (the main thread; I do not spawn any threads myself nor do I submit anything to an ExecutorService) in a relatively simple sequence.
I have noticed that running this in a unit test several times in a row yields different results. Sometimes the classes are created and loaded fine. Other times I get errors from the generated bytecode when it is subsequently used (often in the general area of where I am using withArgumentArrayElements, if it matters; ArrayIndexOutOfBoundsErrors and the like; again other times this all works fine (with the same inputs)).
This feels like a race condition, but as I said I'm not spawning any threads. Since I am not using threads, only ByteBuddy (or the JDK) could be. I am not sure where that would be. Is there a ByteBuddy synchronization mechanism I should be using when creating and loading classes with DynamicTypeBuilder.make() and getLoaded()? Maybe some kind of class resolution is happening (or not happening!) on a background thread or something at make() time, and I am accidentally somehow preventing it from completing? Maybe if I'm going to use these classes immediately (I am) I need to supply a different TypeResolutionStrategy? I am baffled, as should be clear, and cannot figure out why a single-threaded program with the same inputs should produce generated classes that behave differently from run to run.
My pattern for loading these classes is:
Try to load the (normally non-existent) class using Class#forName(name, true, Thread.currentThread().getContextClassLoader()).
If (when) that fails, create the ByteBuddy-generated class and load it using the usual ByteBuddy recipes.
If that fails, it would be only because some other thread might have created the class already. In this unit test, there is no other thread. In any case, if a failure were to occur here, I repeat step 1 and then throw an exception if the load fails.
Are there any ByteBuddy-specific steps I should be taking in addition or instead of these?
Phew! I think I can chalk this up to a bug in my code (thank goodness). Briefly, what looked like concurrency issues was (most likely) an issue with accidentally shared classnames and HashMap iteration order: when one particular subclass was created-and-then-loaded, the other would simply be loaded (not created) and vice versa. The net effect was effects that looked like those of a race condition.
Byte Buddy is fully thread-safe. But it does attempt to create a class every time you invoke load what is a fairly expensive operation. To avoid this, Byte Buddy offers the TypeCache mechanism that allows you to implement an efficient cache.
Note that libraries like cglib offer automatic caching. Byte Buddy does not do this since the cache uses all inputs as keys and references them statically what can easily create memory leaks. Also, the keys are rather inefficient which is why Byte Buddy chose this approach.
It seems to me that singletons enforce a single instance but why would an application that understands that there should be only on such instance even attempt to instantiate a second instance?
I think its also about managing the single shared instance. Synchronization to be precise.You don't want someone to use the resource when you are using it.
Private constructor and static method simply enforces the application to do so.
A lot of developers refrain from using it since its also difficult to test and causes multi-threading issues.
Some Vulkan objects (eg vkPipelines, vkCommandBuffers) are able to be created/allocated in arrays (using size + pointer parameters). At a glance, this appears to be done to make it easier to code using common usage patterns. But in some cases (eg: when creating a C++ RAII wrapper), it's nicer to create them one at a time. It is, of course, simple to achieve this.
However, I'm wondering whether there are any significant downsides to doing this?
(I guess this may vary depending on the actual object type being created - but I didn't think it'd be a good idea to ask the same question for each object)
Assume that, in both cases, objects are likely to be created in a first-created-last-destroyed manner, and that - while the objects are individually created and destroyed - this will likely happen in a loop.
Also note:
vkCommandBuffers are also deallocated in arrays.
vkPipelines are destroyed individually.
Are there any reasons I should modify my RAII wrapper to allow for array-based creation/destruction? For example, will it save memory (significantly)? Will single-creation reduce performance?
Remember that vkPipeline creation does not require external synchronization. That means that the process is going to handle its own mutexes and so forth. As such, it makes sense to avoid locking those internal mutexes whenever possible.
Also, the process is slow. So being able to batch it up and execute it into another thread is very useful.
Command buffer creation doesn't have either of these concerns. So there, you should feel free to allocate whatever CBs you need. However, multiple creation will never harm performance, and it may help it. So there's no reason to avoid it.
Vulkan is an API designed around modern graphics hardware. If you know you want to create a certain number of objects up front, you should use the batch functions if they exist, as the driver may be able to optimize creation/allocation, resulting in potentially better performance.
There may (or may not) be better performance (depending on driver and the type of your workload). But there is obviously potential for better performance.
If you create one or ten command buffers in you application then it does not matter.
For most cases it will be like less than 5 %. So if you do not care about that (e.g. your application already runs 500 FPS), then it does not matter.
Then again, C++ is a versatile language. I think this is a non-problem. You would simply have a static member function or a class that would construct/initialize N objects (there's probably a pattern name for that).
The destruction may be trickier. You can again have static member function that would destroy N objects. But it would not be called automatically and it is annoying to have null/husk objects around. And the destructor would still be called on VK_NULL_HANDLE. There is also a problem, that a pool reset or destruction would invalidate all the command buffer C++ objects, so there's probably no way to do it cleanly/simply.
I have a two questions:
1.) On tearDown method of mocks.
People says that its a common practice to set all the mocks to null in teardown method like below:
public void tearDown(){
mockOne=null;
mockTwo=null;
}
I want to know does this really make sense or we should be doing something useful in the tearDown?
JVM will not take care to nullify the mocks?
) Also, whether all the variables that are being used in the jUnit should be defined at class level or at method level? I know creating at class level promotes code reuse but will it not uncessarary occupy memory all the time in maintaining the state?
Thanks.
To your first point, I would say that I personally seldom if ever have a use for a tearDown() method, certainly not to lose a reference to a mock object. I am not inclined to believe "people" on that one.
To your second point, just declare your variables in the smallest scope that you possibly can as what is paramount is that your tests both capture some required behavior and are easily comprehended.
As per usual, keep it simple and strive to have very minimal setup (Arrange), invocation of test subject (Act) and verification (Assert) in each test. If you have trouble with this, it's a sign that your test subject (or class under test) may be doing too much.
1.
I don't think your tearDown does a whole lot of useful things. Your test cases will usually be running on a different VM from the production server VMs, so there's no need to be so cautious about GC (if that's what the intention of setting the mocks to null is). The mock objects among the stubs that your test classes create will be eligible for GC as soon as they go out of scope, which is at worst, after execution of all the test cases and exiting of the JVM.
Sure it might help the garbage-collector reclaim these resources sooner than without it, but unless you run a really large suite of unit tests, this can't be a problem.
If, on the other hand, the idea is to make sure the changes made to the mock objects by one test method do not affect another subsequent test method, this makes sense somewhat.
Don't overthink these fixtures - have something to setup for the subsequent test case(s)? Do it in the #Before annotated setUp method. Have something like cleaning up resources like the database connections and system resources? Do it in the After annotated tearDown method.
Normally, you'll not even write a tearDown method unless you're faced with one of the above said requirements unlike the setUp method which might prove far more useful to you.
2.
My first point above partly answers your questions related to the memory footprint. There's no need to be so cautious with the unit tests.
You'd typically not write unit tests that are long running processes.
Besides, creating the objects closer to where you use them and limiting their scope and exposure to a required minimum is generally a good practice - so if you are not planning to reuse the objects/mocks, feel free to create them (and thereby make them go out of scope as soon as the test method completes the execution) in your test methods.
Not during instantiation, but once instantiation of singleton object is done, what will happen if two or more threads are trying to access the same singleton object? Especially in the case where the singleton object takes lot of time to process the request (say 1 min)... In this case, if for ex., 5 threads try to access the same singleton object, what will the result be?
Additional question: normally when should we go for the singleton pattern and when should we avoid it?
Unless synchronization (locking) is being performed within the Singleton, the answer is this: it's a free-for-all.
Though the Singleton ensures that only one instance of an object is used when requested, the pattern itself doesn't inherently provide any form of thread safety. This is left up to the implementer.
In the specific case you cited (with a long running method), it would be critical to synchronize access to any method that uses class or object-level variables. Failure to do so would, in all likelihood, lead to race conditions.
Good luck!
The general rule of thumb i use for Singletons is that it should not affect the running code, and have no side-effects. Essentially for me, in my projects this translates into some kind of logging functionality, or static value lookup (ie. loading some common data from a database once and storing it for reference so it doesn't have to be read in everytime its needed).
A singleton is no different than any other object other than there is only one instance. What happens when you try to access it will largely depend on what the accessing threads are attempting (ie read vs write) and what kind of data your singleton is holding.
The answer to your question as it is, is "it really depends". What kind of singleton? i.e. what does it do, and how does it do it? And in what language?
The reality is that the singleton patter)n only dictates and enforces that you can only have one instance of a certain object. In of itself it does not say anything about multiple threads accessing that object.
So, if coded right (with thread synchronization implemented correctly) there is no reason why it shouldn't behave correctly - even if the requests to the object take a really long time to process!
Then you need thread safe implementation of singleton pattern.
Find this article useful for the same which describes most of the multi-threading scenario of singleton pattern.
HTH!