-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove controller from unit tests #164
Remove controller from unit tests #164
Conversation
ce89023
to
6d17b9c
Compare
pkg/virt-controller/watch/job.go
Outdated
@@ -15,7 +15,7 @@ import ( | |||
"kubevirt.io/kubevirt/pkg/virt-controller/services" | |||
) | |||
|
|||
func migrationJobSelector() kubeapi.ListOptions { | |||
func MigrationJobSelector() kubeapi.ListOptions { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the rationale behind making this a public function? It's fine to do that, but the "panic" instruction in this code should instead return an error if this is to be a general purpose function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returned to private naming
if err != nil { | ||
logger.Error().Reason(err).Msg("updating migration state failed") | ||
logger.Error().Reason(err).Msg("creating am migration target node failed") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo
371b3d5
to
c95ce1e
Compare
retest this please |
c95ce1e
to
e3f0293
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of my comments are nitpicky. The most important one to look at is the mergeConstraints question.
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
"github.com/onsi/gomega/ghttp" | ||
"k8s.io/client-go/kubernetes" | ||
"net/http" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like your IDE decided to move this line
} | ||
} | ||
vm.Spec.NodeSelector = merged |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might want to run this line after the "if len(conflicts) > 0" block. This makes a side-effect change since VM was passed in by pointer, so we should check that there are no errors first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, that should be after the check.
close(done) | ||
}, 10) | ||
|
||
It("should fail if confliciting VM and Migration have conflicting Node Selectors", func(done Done) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: "confliciting"
pkg/virt-handler/domain.go
Outdated
queue.AddRateLimited(key) | ||
} else if !vmExists || obj.(*v1.VM).GetObjectMeta().GetUID() != domain.GetObjectMeta().GetUID() { | ||
obj, vmExists, _ := d.vmStore.GetByKey(key.(string)) | ||
// GetByKey cannot return an error, leading the error handling code |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Technically this comment refers to non-existent code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It explains why the err in the above line is ignored.
pkg/virt-handler/domain_test.go
Outdated
"kubevirt.io/kubevirt/pkg/logging" | ||
. "kubevirt.io/kubevirt/pkg/virt-handler" | ||
"kubevirt.io/kubevirt/pkg/virt-handler/virtwrap" | ||
"time" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong import order
pkg/virt-handler/domain_test.go
Outdated
Consistently(vmQueue.Len).Should(Equal(0)) | ||
}) | ||
|
||
It("should create not requeue even if domain reference if it is not in the cache", func() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should not create?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dropped the "create"
close(done) | ||
}, 10) | ||
|
||
It("Should mark Migation failed if VM not running ", func(done Done) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: "Migation"
|
||
Expect(len(server.ReceivedRequests())).To(Equal(5)) | ||
Expect(len(server.ReceivedRequests())).To(Equal(7)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wish there were a better way to test this (I'm not saying there is). The number of API calls made by any given section of code is a good candidate for something likely to change--so this test could unexpectedly fail in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that is all right, since we have to mock this layer, there is no way around it. I would not like to have rest calls lying aroung which are not even used.
But: Instead of checking this explicitly I would add one check in the AfterEach section which makes sure that the amount of registered calls equals the amount of expected calls. The nwe can remove this line from the test itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, but there is no way to get a count of the registered handlers, so the logic here is as simple as we can get.
pkg/virt-controller/watch/job.go
Outdated
@@ -55,12 +50,9 @@ type JobDispatch struct { | |||
|
|||
func (jd *JobDispatch) Execute(store cache.Store, queue workqueue.RateLimitingInterface, key interface{}) { | |||
// Fetch the latest Job state from cache | |||
obj, exists, err := store.GetByKey(key.(string)) | |||
// Cannot return an error | |||
obj, exists, _ := store.GetByKey(key.(string)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The controller loop has no idea which cache implementation is used, so I would say that it is not it's job to guess about the internals.
@@ -55,12 +50,9 @@ func (md *MigrationDispatch) Execute(store cache.Store, queue workqueue.RateLimi | |||
} | |||
|
|||
// Fetch the latest Migration state from cache | |||
obj, exists, err := store.GetByKey(key.(string)) | |||
// error is always nil | |||
obj, exists, _ := store.GetByKey(key.(string)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, I would expect the error although, the current used store does not throw one ...
} | ||
} | ||
vm.Spec.NodeSelector = merged |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, that should be after the check.
expectedMigration := obj.(*v1.Migration) | ||
expectedMigration.Status.Phase = expectedStatus | ||
expectedMigration.Kind = "Migration" | ||
expectedMigration.APIVersion = "kubevirt.io/v1alpha1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting all these fields looks strange. I think it is better if you only explicitly set fields which are relevant for the test.
Self link, ... are not something we need to check here ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are set by the calling code, and we need to confirm a match. Any other logic would be more complicated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I meant is that you are copying the object anyway already. So you are overriding for the test unimportant fields with the value which it already contains (like self link, ...).
Since you are copying it already, just overriding the fields with the expected changes should do ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The checks need a few cleanups:
- On requeue we need to check for the history of the key too
- We always have to check if the queue is empty after a call which should be successful
doExecute() | ||
|
||
Expect(len(server.ReceivedRequests())).To(Equal(2)) | ||
Eventually(jobQueue.Len()).Should(Equal(1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A check if we have a history of the key is missing: queue.NumRequeues(key) == 1
doExecute() | ||
|
||
Expect(len(server.ReceivedRequests())).To(Equal(3)) | ||
Eventually(jobQueue.Len()).Should(Equal(1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A check if we have a history of the key is missing
Expect(len(server.ReceivedRequests())).To(Equal(4)) | ||
Eventually(jobQueue.Len()).Should(Equal(1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A check if we have a history of the key is missing
) | ||
|
||
doExecute() | ||
Expect(len(server.ReceivedRequests())).To(Equal(4)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you are not testing if the queue is now empty.
// Create the expected VM after the update | ||
obj, err := conversion.NewCloner().DeepCopy(vm) | ||
Expect(err).ToNot(HaveOccurred()) | ||
Expect(len(server.ReceivedRequests())).To(Equal(4)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to check if the queue is empty.
doExecute() | ||
|
||
Expect(len(server.ReceivedRequests())).To(Equal(1)) | ||
Eventually(queue.Len()).Should(Equal(1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Expect
doExecute() | ||
|
||
Expect(len(server.ReceivedRequests())).To(Equal(3)) | ||
Eventually(queue.Len()).Should(Equal(1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Expect
doExecute() | ||
|
||
Expect(len(server.ReceivedRequests())).To(Equal(3)) | ||
Eventually(queue.Len()).Should(Equal(1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Expect
doExecute() | ||
|
||
Expect(len(server.ReceivedRequests())).To(Equal(3)) | ||
Eventually(queue.Len()).Should(Equal(1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Expect
doExecute() | ||
|
||
Expect(len(server.ReceivedRequests())).To(Equal(3)) | ||
Eventually(queue.Len()).Should(Equal(1)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Expect
@admiyo one of the functional tests failed, could you check if there is something behind it? |
e3f0293
to
8fc7024
Compare
That is just the rebase: have not addressed comments yet. |
pkg/virt-handler/domain.go
Outdated
return | ||
} | ||
obj, exists, _ := indexer.GetByKey(key.(string)) | ||
// GetByKey can never return anything but nil for the error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@admiyo , you could use your own store implementation (A store is an interface) which can throw an error, if that is your line of agrumentation. Every code in kubernetes itself is also taking this error into account.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its a bug, then, in the library we are using.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? There is an interface which says, return an error if there is one, but that does not mean that every implementation necessarily is written in a way that there can happen an error to report.
The most extreme examples: Think of an in memory map, which can't have an error when looking up a key. It is a valid implementation of a store and when accessed through the interface, you always return nil as an error. Now think of a file based store. When looking something there up, it can fail.
The interface is the contract I would want to implement. I don't think it is nice, to assume a concrete implementation behind an interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that, if I add it back in, we'll still be under the threshold for untestable code. Let's see.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
of course this can be tested. create a cache class that throws an error.
fix travis-9
No description provided.