Copilot commented on code in PR #846:
URL: https://github.com/apache/solr-operator/pull/846#discussion_r4514359922


##########
controllers/util/backup_util.go:
##########
@@ -124,6 +124,12 @@ func CheckBackupForCollection(ctx context.Context, cloud 
*solr.SolrCloud, collec
                        finished = true
                        success = false
                }
+               if asyncStatus == "notfound" {
+                       finished = true
+                       success = false
+                       logger.Info("Solr has no record of the collection 
backup, so it cannot be confirmed. Marking it unsuccessful; the backup 
repository may still contain a usable backup.",
+                               "solrCloud", cloud.Name, "collection", 
collection)
+               }

Review Comment:
   The status handling is now a growing chain of independent `if` statements 
comparing string literals. Converting this to a `switch asyncStatus` (or `else 
if` chain) makes exclusivity explicit and reduces the chance of accidental 
double-handling as more states are added. Also consider centralizing 
`"completed"`, `"failed"`, and `"notfound"` into constants (ideally shared with 
`solr_api`) to avoid typo-prone string duplication.



##########
controllers/util/backup_util_test.go:
##########
@@ -413,3 +427,51 @@ func 
TestRepositoryLookupFailsIfNoNameProvidedAndMultipleRepositoriesDefined(t *
 
        assert.Nil(t, found, "Expected GetBackupRepositoryByName to report no 
match")
 }
+
+// A backup whose async status Solr no longer holds must be terminal, 
otherwise it is checked
+// forever. It is unsuccessful because success cannot be shown, not because 
failure is known.
+func TestCheckBackupForCollectionOutcome(t *testing.T) {
+       tests := map[string]struct {
+               finished bool
+               success  bool
+       }{
+               "completed": {finished: true, success: true},
+               "failed":    {finished: true, success: false},
+               "notfound":  {finished: true, success: false},
+               "running":   {finished: false, success: false},
+               "submitted": {finished: false, success: false},
+       }
+
+       defer func() {
+               transport := http.DefaultTransport.(*http.Transport).Clone()
+               transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: 
true}
+               solr_api.SetNoVerifyTLSHttpClient(&http.Client{Transport: 
transport})
+       }()
+
+       for asyncStatus, expected := range tests {
+               solr_api.SetNoVerifyTLSHttpClient(&http.Client{Transport: 
roundTripFunc(func(request *http.Request) (*http.Response, error) {
+                       assert.Equal(t, "REQUESTSTATUS", 
request.URL.Query().Get("action"))
+                       assert.Equal(t, "backup-collection", 
request.URL.Query().Get("requestid"))
+                       return &http.Response{
+                               StatusCode: http.StatusOK,
+                               Header:     make(http.Header),
+                               Body: 
io.NopCloser(strings.NewReader(fmt.Sprintf(
+                                       
`{"responseHeader":{"status":0},"status":{"state":%q}}`, asyncStatus,
+                               ))),
+                       }, nil
+               })})
+
+               finished, success, actualStatus, err := 
CheckBackupForCollection(
+                       context.Background(),
+                       &solr.SolrCloud{ObjectMeta: metav1.ObjectMeta{Name: 
"cloud", Namespace: "namespace"}},
+                       "collection",
+                       "backup",
+                       logr.Discard(),
+               )
+
+               assert.NoError(t, err)
+               assert.Equal(t, asyncStatus, actualStatus)
+               assert.Equal(t, expected.finished, finished, "Wrong finished 
for async status %q", asyncStatus)
+               assert.Equal(t, expected.success, success, "Wrong success for 
async status %q", asyncStatus)

Review Comment:
   This test mutates a global HTTP client in `solr_api` (multiple times inside 
the loop) without restoring the previous client value. That can leak state into 
other tests and introduces flakiness if other tests run in parallel within the 
package (or if `t.Parallel()` is added later). Prefer capturing/restoring the 
previous client via a getter (or adding one), or avoid global mutation by 
injecting the HTTP client/transport into the code under test; at minimum, 
restore the original client with `t.Cleanup` to prevent cross-test interference.



##########
controllers/util/backup_util_test.go:
##########
@@ -413,3 +427,51 @@ func 
TestRepositoryLookupFailsIfNoNameProvidedAndMultipleRepositoriesDefined(t *
 
        assert.Nil(t, found, "Expected GetBackupRepositoryByName to report no 
match")
 }
+
+// A backup whose async status Solr no longer holds must be terminal, 
otherwise it is checked
+// forever. It is unsuccessful because success cannot be shown, not because 
failure is known.
+func TestCheckBackupForCollectionOutcome(t *testing.T) {
+       tests := map[string]struct {
+               finished bool
+               success  bool
+       }{
+               "completed": {finished: true, success: true},
+               "failed":    {finished: true, success: false},
+               "notfound":  {finished: true, success: false},
+               "running":   {finished: false, success: false},
+               "submitted": {finished: false, success: false},
+       }
+
+       defer func() {
+               transport := http.DefaultTransport.(*http.Transport).Clone()
+               transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: 
true}
+               solr_api.SetNoVerifyTLSHttpClient(&http.Client{Transport: 
transport})
+       }()
+
+       for asyncStatus, expected := range tests {
+               solr_api.SetNoVerifyTLSHttpClient(&http.Client{Transport: 
roundTripFunc(func(request *http.Request) (*http.Response, error) {
+                       assert.Equal(t, "REQUESTSTATUS", 
request.URL.Query().Get("action"))
+                       assert.Equal(t, "backup-collection", 
request.URL.Query().Get("requestid"))
+                       return &http.Response{
+                               StatusCode: http.StatusOK,
+                               Header:     make(http.Header),
+                               Body: 
io.NopCloser(strings.NewReader(fmt.Sprintf(
+                                       
`{"responseHeader":{"status":0},"status":{"state":%q}}`, asyncStatus,
+                               ))),
+                       }, nil
+               })})
+
+               finished, success, actualStatus, err := 
CheckBackupForCollection(
+                       context.Background(),
+                       &solr.SolrCloud{ObjectMeta: metav1.ObjectMeta{Name: 
"cloud", Namespace: "namespace"}},
+                       "collection",
+                       "backup",
+                       logr.Discard(),
+               )
+
+               assert.NoError(t, err)
+               assert.Equal(t, asyncStatus, actualStatus)
+               assert.Equal(t, expected.finished, finished, "Wrong finished 
for async status %q", asyncStatus)
+               assert.Equal(t, expected.success, success, "Wrong success for 
async status %q", asyncStatus)

Review Comment:
   `assert.Equal`’s `msgAndArgs` is not printf-formatted in testify; passing a 
format string plus args won’t substitute `%q`, leading to confusing failure 
output. Use `assert.Equalf(...)` (or build the message with `fmt.Sprintf`) so 
the asyncStatus is interpolated correctly.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to