Repository: owncloud/ocis
Pull request #11334 (2025-05-21 06:36:33)

chore(deps): bump gotest.tools/v3 from 3.5.1 to 3.5.2
Bumps [gotest.tools/v3](https://github.com/gotestyourself/gotest.tools) from 3.5.1 to 3.5.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/gotestyourself/gotest.tools/releases">gotest.tools/v3's releases</a>.</em></p>
<blockquote>
<h2>v3.5.2</h2>
<h2>What's Changed</h2>
<ul>
<li>assert: ensure message is always displayed &amp; fix under bazel by <a href="https://github.com/cstrahan"><code>@​cstrahan</code></a> in <a href="https://redirect.github.com/gotestyourself/gotest.tools/pull/276">gotestyourself/gotest.tools#276</a></li>
<li>go.mod: golang.org/x/tools v0.13.0 for go1.22+ compatibility by <a href="https://github.com/thaJeztah"><code>@​thaJeztah</code></a> in <a href="https://redirect.github.com/gotestyourself/gotest.tools/pull/282">gotestyourself/gotest.tools#282</a></li>
<li>poll: Continue(): use format.Message for formatting by <a href="https://github.com/thaJeztah"><code>@​thaJeztah</code></a> in <a href="https://redirect.github.com/gotestyourself/gotest.tools/pull/279">gotestyourself/gotest.tools#279</a></li>
<li>fix TestFromDirSymlink on Windows due to missing drive-letter by <a href="https://github.com/thaJeztah"><code>@​thaJeztah</code></a> in <a href="https://redirect.github.com/gotestyourself/gotest.tools/pull/283">gotestyourself/gotest.tools#283</a></li>
<li>Fix various linting issues and minor bugs by <a href="https://github.com/thaJeztah"><code>@​thaJeztah</code></a> in <a href="https://redirect.github.com/gotestyourself/gotest.tools/pull/280">gotestyourself/gotest.tools#280</a></li>
<li>fix badges in readme, gofmt, and minor linting fix by <a href="https://github.com/thaJeztah"><code>@​thaJeztah</code></a> in <a href="https://redirect.github.com/gotestyourself/gotest.tools/pull/284">gotestyourself/gotest.tools#284</a></li>
<li>circleci: add go1.21, go1.22, go1.23, and update golangci-lint to v1.60.3 by <a href="https://github.com/thaJeztah"><code>@​thaJeztah</code></a> in <a href="https://redirect.github.com/gotestyourself/gotest.tools/pull/285">gotestyourself/gotest.tools#285</a></li>
<li>assert, assert/cmp: un-deprecate assert.ErrorType for now by <a href="https://github.com/thaJeztah"><code>@​thaJeztah</code></a> in <a href="https://redirect.github.com/gotestyourself/gotest.tools/pull/286">gotestyourself/gotest.tools#286</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/cstrahan"><code>@​cstrahan</code></a> made their first contribution in <a href="https://redirect.github.com/gotestyourself/gotest.tools/pull/276">gotestyourself/gotest.tools#276</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a href="https://github.com/gotestyourself/gotest.tools/compare/v3.5.1...v3.5.2">https://github.com/gotestyourself/gotest.tools/compare/v3.5.1...v3.5.2</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/gotestyourself/gotest.tools/commit/0b81523ff268a1f1b0baf4a5da67e42fbb86880b"><code>0b81523</code></a> Merge pull request <a href="https://redirect.github.com/gotestyourself/gotest.tools/issues/286">#286</a> from thaJeztah/undeprecate_ErrorType</li>
<li><a href="https://github.com/gotestyourself/gotest.tools/commit/c5dad8f46d9147674b5aac2c1207acdbb6e44cbc"><code>c5dad8f</code></a> Merge pull request <a href="https://redirect.github.com/gotestyourself/gotest.tools/issues/285">#285</a> from thaJeztah/update_go_versions</li>
<li><a href="https://github.com/gotestyourself/gotest.tools/commit/160ab0edaf37dd48cb0bcda12a713b2eda21254e"><code>160ab0e</code></a> Remove go1.18 and go1.19</li>
<li><a href="https://github.com/gotestyourself/gotest.tools/commit/8569bbc4e11f8a77c32795751b309c618f001bcc"><code>8569bbc</code></a> Merge pull request <a href="https://redirect.github.com/gotestyourself/gotest.tools/issues/284">#284</a> from thaJeztah/cleanup_readme</li>
<li><a href="https://github.com/gotestyourself/gotest.tools/commit/4256834a5f656a2b6d8b8ee1e05ac7048b3028a0"><code>4256834</code></a> assert, assert/cmp: un-deprecate assert.ErrorType for now</li>
<li><a href="https://github.com/gotestyourself/gotest.tools/commit/eb321863bacc768e4f24e8ec7c0efc1f6144bcc4"><code>eb32186</code></a> circleci: update golangci-lint to v1.60.3</li>
<li><a href="https://github.com/gotestyourself/gotest.tools/commit/5fc84733cf3804f0e6267370df3d83b582f44b13"><code>5fc8473</code></a> circleci: add go1.21, go1.22, go1.23</li>
<li><a href="https://github.com/gotestyourself/gotest.tools/commit/6f26df9681dce743fd0c5c0e8e5d9810a4d47f3c"><code>6f26df9</code></a> circleci: test generics on go1.20 and windows as well</li>
<li><a href="https://github.com/gotestyourself/gotest.tools/commit/732dfcf754771fd19a3f374355bdad313b47d4c0"><code>732dfcf</code></a> internal/difflib: rename funcs that collided with built-ins</li>
<li><a href="https://github.com/gotestyourself/gotest.tools/commit/7d95f55d2ce979847b6207fedd071831fe7c39dc"><code>7d95f55</code></a> internal/difflib: gofmt</li>
<li>Additional commits viewable in <a href="https://github.com/gotestyourself/gotest.tools/compare/v3.5.1...v3.5.2">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=gotest.tools/v3&package-manager=go_modules&previous-version=3.5.1&new-version=3.5.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

update-docs[bot]: Thanks for opening this pull request! The maintainers of this repository would appreciate it if you would create a [changelog](https://github.com/owncloud/ocis/blob/master/changelog/README.md) item based on your changes.

sonarqubecloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=11334) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=11334&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=11334&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=11334&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=11334&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=11334&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=11334)



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0aa47564943..1b4463403c7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -77,6 +77,7 @@ The following sections list the changes for unreleased.
 * Bugfix - Fix app-auth, REST status code: [#11190](https://github.com/owncloud/ocis/pull/11190)
 * Bugfix - Fix Share roles translation: [#11241](https://github.com/owncloud/ocis/pull/11241)
 * Bugfix - Fix error on listing space members: [#11245](https://github.com/owncloud/ocis/pull/11245)
+* Bugfix - Fix collaboration service LastModifiedDate: [#11328](https://github.com/owncloud/ocis/pull/11328)
 * Enhancement - Update Mockery to 2.52.3: [#11070](https://github.com/owncloud/ocis/pull/11070)
 * Enhancement - Improve postprocessing logs: [#11108](https://github.com/owncloud/ocis/pull/11108)
 * Enhancement - Improve graph space management logs: [#11115](https://github.com/owncloud/ocis/pull/11115)
@@ -190,6 +191,12 @@ The following sections list the changes for unreleased.
    https://github.com/owncloud/ocis/issues/11119
    https://github.com/owncloud/ocis/pull/11245
 
+* Bugfix - Fix collaboration service LastModifiedDate: [#11328](https://github.com/owncloud/ocis/pull/11328)
+
+   Collaboration service now returns correct LastModifiedDate.
+
+   https://github.com/owncloud/ocis/pull/11328
+
 * Enhancement - Update Mockery to 2.52.3: [#11070](https://github.com/owncloud/ocis/pull/11070)
 
    Without updating ocis will not build on go 1.24. This requires also updating the
diff --git a/changelog/unreleased/fix-collaboration-lastmodifieddate.md b/changelog/unreleased/fix-collaboration-lastmodifieddate.md
new file mode 100644
index 00000000000..deea89a3438
--- /dev/null
+++ b/changelog/unreleased/fix-collaboration-lastmodifieddate.md
@@ -0,0 +1,5 @@
+Bugfix: Fix collaboration service LastModifiedDate
+
+Collaboration service now returns correct LastModifiedDate.
+
+https://github.com/owncloud/ocis/pull/11328
diff --git a/go.mod b/go.mod
index 48464436325..2bca101c147 100644
--- a/go.mod
+++ b/go.mod
@@ -110,7 +110,7 @@ require (
 	google.golang.org/grpc v1.71.1
 	google.golang.org/protobuf v1.36.6
 	gopkg.in/yaml.v2 v2.4.0
-	gotest.tools/v3 v3.5.1
+	gotest.tools/v3 v3.5.2
 	stash.kopano.io/kgol/rndm v1.1.2
 )
 
diff --git a/go.sum b/go.sum
index b07d733a4e2..6b73acf8ae6 100644
--- a/go.sum
+++ b/go.sum
@@ -1690,8 +1690,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
 gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
-gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
-gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
+gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
+gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
 honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/services/collaboration/pkg/connector/fileconnector.go b/services/collaboration/pkg/connector/fileconnector.go
index ef27188e886..c6ee19c39ee 100644
--- a/services/collaboration/pkg/connector/fileconnector.go
+++ b/services/collaboration/pkg/connector/fileconnector.go
@@ -40,6 +40,11 @@ const (
 	// WOPI Locks generally have a lock duration of 30 minutes and will be refreshed before expiration if needed
 	// https://docs.microsoft.com/en-us/microsoft-365/cloud-storage-partner-program/rest/concepts#lock
 	lockDuration time.Duration = 30 * time.Minute
+
+	// Expected format for LastModifiedTime is ISO 8601 round-trip format (e.g. "2009-06-15T13:45:30.0000000Z")
+	// see: https://learn.microsoft.com/en-us/microsoft-365/cloud-storage-partner-program/rest/files/checkfileinfo/checkfileinfo-other#lastmodifiedtime
+	// and: https://pkg.go.dev/time#Time.Format
+	timeFormat = "2006-01-02T15:04:05.0000000Z"
 )
 
 // FileConnectorService is the interface to implement the "Files"
@@ -1254,10 +1259,16 @@ func (f *FileConnector) CheckFileInfo(ctx context.Context) (*ConnectorResponse,
 		}
 	}
 
+	lastModifiedTime := time.Now().UTC().Format(timeFormat)
+	if statRes.GetInfo().GetMtime() != nil {
+		lastModifiedTime = time.Unix(int64(statRes.GetInfo().GetMtime().GetSeconds()), int64(statRes.GetInfo().GetMtime().GetNanos())).UTC().Format(timeFormat)
+	}
+
 	infoMap := map[string]interface{}{
 		fileinfo.KeyOwnerID:           hexEncodedOwnerId,
 		fileinfo.KeySize:              size,
 		fileinfo.KeyVersion:           getVersion(statRes.GetInfo().GetMtime()),
+		fileinfo.KeyLastModifiedTime:  lastModifiedTime,
 		fileinfo.KeyBaseFileName:      path.Base(statRes.GetInfo().GetPath()),
 		fileinfo.KeyBreadcrumbDocName: path.Base(statRes.GetInfo().GetPath()),
 		// to get the folder we actually need to do a GetPath() request
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 39a80bf5cd3..52a0b8a0d5c 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -2425,7 +2425,7 @@ gopkg.in/yaml.v2
 # gopkg.in/yaml.v3 v3.0.1
 ## explicit
 gopkg.in/yaml.v3
-# gotest.tools/v3 v3.5.1
+# gotest.tools/v3 v3.5.2
 ## explicit; go 1.17
 gotest.tools/v3/assert
 gotest.tools/v3/assert/cmp


Test patch:
diff --git a/services/collaboration/pkg/connector/fileconnector_test.go b/services/collaboration/pkg/connector/fileconnector_test.go
index bfecffbf195..57618cc11b1 100644
--- a/services/collaboration/pkg/connector/fileconnector_test.go
+++ b/services/collaboration/pkg/connector/fileconnector_test.go
@@ -1703,6 +1703,7 @@ var _ = Describe("FileConnector", func() {
 					Size: uint64(998877),
 					Mtime: &typesv1beta1.Timestamp{
 						Seconds: uint64(16273849),
+						Nanos:   uint32(123456789),
 					},
 					Path: "/path/to/test.txt",
 					Id: &providerv1beta1.ResourceId{
@@ -1721,7 +1722,8 @@ var _ = Describe("FileConnector", func() {
 			expectedFileInfo := &fileinfo.Microsoft{
 				OwnerID:                    "61616262636340637573746f6d496470", // hex of aabbcc@customIdp
 				Size:                       int64(998877),
-				Version:                    "v162738490",
+				Version:                    "v16273849123456789",
+				LastModifiedTime:           "1970-07-08T08:30:49.1234567Z",
 				BaseFileName:               "test.txt",
 				BreadcrumbDocName:          "test.txt",
 				BreadcrumbFolderName:       "/path/to",
@@ -1777,6 +1779,7 @@ var _ = Describe("FileConnector", func() {
 					// Size is intentionally nil for guest users
 					Mtime: &typesv1beta1.Timestamp{
 						Seconds: uint64(16273849),
+						Nanos:   uint32(1234567),
 					},
 					Path: "/path/to/test.txt",
 					Id: &providerv1beta1.ResourceId{
@@ -1879,6 +1882,7 @@ var _ = Describe("FileConnector", func() {
 					// Size is intentionally nil for guest users
 					Mtime: &typesv1beta1.Timestamp{
 						Seconds: uint64(16273849),
+						Nanos:   uint32(123456789),
 					},
 					Path: "/path/to/test.txt",
 					Id:   ResourceId,
@@ -1896,7 +1900,8 @@ var _ = Describe("FileConnector", func() {
 			cfg.App.Product = "OnlyOffice"
 
 			expectedFileInfo := &fileinfo.OnlyOffice{
-				Version:                 "v162738490",
+				Version:                 "v16273849123456789",
+				LastModifiedTime:        "1970-07-08T08:30:49.1234567Z",
 				BaseFileName:            "test.txt",
 				BreadcrumbDocName:       "test.txt",
 				BreadcrumbFolderName:    "/path/to",
@@ -2049,6 +2054,7 @@ var _ = Describe("FileConnector", func() {
 
 			expectedFileInfo := &fileinfo.OnlyOffice{
 				Version:                 "v162738490",
+				LastModifiedTime:        "1970-07-08T08:30:49.0000000Z",
 				BaseFileName:            "test.txt",
 				BreadcrumbDocName:       "test.txt",
 				BreadcrumbFolderName:    "/path/to",
diff --git a/vendor/gotest.tools/v3/assert/assert.go b/vendor/gotest.tools/v3/assert/assert.go
index c418bd07b5c..ae62cefec15 100644
--- a/vendor/gotest.tools/v3/assert/assert.go
+++ b/vendor/gotest.tools/v3/assert/assert.go
@@ -284,8 +284,6 @@ func ErrorContains(t TestingT, err error, substring string, msgAndArgs ...interf
 // must be called from the goroutine running the test function, not from other
 // goroutines created during the test. Use [Check] with [cmp.ErrorType] from other
 // goroutines.
-//
-// Deprecated: Use [ErrorIs]
 func ErrorType(t TestingT, err error, expected interface{}, msgAndArgs ...interface{}) {
 	if ht, ok := t.(helperT); ok {
 		ht.Helper()
diff --git a/vendor/gotest.tools/v3/assert/cmp/compare.go b/vendor/gotest.tools/v3/assert/cmp/compare.go
index 118844f35d0..a7507e6591e 100644
--- a/vendor/gotest.tools/v3/assert/cmp/compare.go
+++ b/vendor/gotest.tools/v3/assert/cmp/compare.go
@@ -248,7 +248,7 @@ type causer interface {
 }
 
 func formatErrorMessage(err error) string {
-	//nolint:errorlint // unwrapping is not appropriate here
+	//nolint:errorlint,nolintlint // unwrapping is not appropriate here
 	if _, ok := err.(causer); ok {
 		return fmt.Sprintf("%q\n%+v", err, err)
 	}
@@ -286,6 +286,7 @@ func isNil(obj interface{}, msgFunc func(reflect.Value) string) Comparison {
 }
 
 // ErrorType succeeds if err is not nil and is of the expected type.
+// New code should use [ErrorIs] instead.
 //
 // Expected can be one of:
 //
@@ -306,8 +307,6 @@ func isNil(obj interface{}, msgFunc func(reflect.Value) string) Comparison {
 //	reflect.Type
 //
 // Fails if err does not implement the [reflect.Type].
-//
-// Deprecated: Use [ErrorIs]
 func ErrorType(err error, expected interface{}) Comparison {
 	return func() Result {
 		switch expectedType := expected.(type) {
diff --git a/vendor/gotest.tools/v3/internal/assert/assert.go b/vendor/gotest.tools/v3/internal/assert/assert.go
index 2dd80255ab5..1e8727682c5 100644
--- a/vendor/gotest.tools/v3/internal/assert/assert.go
+++ b/vendor/gotest.tools/v3/internal/assert/assert.go
@@ -87,19 +87,18 @@ func logFailureFromBool(t LogT, msgAndArgs ...interface{}) {
 	args, err := source.CallExprArgs(stackIndex)
 	if err != nil {
 		t.Log(err.Error())
-		return
 	}
 
+	var msg string
 	const comparisonArgIndex = 1 // Assert(t, comparison)
 	if len(args) <= comparisonArgIndex {
-		t.Log(failureMessage + "but assert failed to find the expression to print")
-		return
-	}
-
-	msg, err := boolFailureMessage(args[comparisonArgIndex])
-	if err != nil {
-		t.Log(err.Error())
-		msg = "expression is false"
+		msg = "but assert failed to find the expression to print"
+	} else {
+		msg, err = boolFailureMessage(args[comparisonArgIndex])
+		if err != nil {
+			t.Log(err.Error())
+			msg = "expression is false"
+		}
 	}
 
 	t.Log(format.WithCustomMessage(failureMessage+msg, msgAndArgs...))
diff --git a/vendor/gotest.tools/v3/internal/difflib/difflib.go b/vendor/gotest.tools/v3/internal/difflib/difflib.go
index 9bf506b6be0..bedacca3e52 100644
--- a/vendor/gotest.tools/v3/internal/difflib/difflib.go
+++ b/vendor/gotest.tools/v3/internal/difflib/difflib.go
@@ -1,4 +1,5 @@
-/*Package difflib is a partial port of Python difflib module.
+/*
+Package difflib is a partial port of Python difflib module.
 
 Original source: https://github.com/pmezard/go-difflib
 
@@ -6,14 +7,14 @@ This file is trimmed to only the parts used by this repository.
 */
 package difflib // import "gotest.tools/v3/internal/difflib"
 
-func min(a, b int) int {
+func minInt(a, b int) int {
 	if a < b {
 		return a
 	}
 	return b
 }
 
-func max(a, b int) int {
+func maxInt(a, b int) int {
 	if a > b {
 		return a
 	}
@@ -170,12 +171,15 @@ func (m *SequenceMatcher) isBJunk(s string) bool {
 // If IsJunk is not defined:
 //
 // Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where
-//     alo <= i <= i+k <= ahi
-//     blo <= j <= j+k <= bhi
+//
+//	alo <= i <= i+k <= ahi
+//	blo <= j <= j+k <= bhi
+//
 // and for all (i',j',k') meeting those conditions,
-//     k >= k'
-//     i <= i'
-//     and if i == i', j <= j'
+//
+//	k >= k'
+//	i <= i'
+//	and if i == i', j <= j'
 //
 // In other words, of all maximal matching blocks, return one that
 // starts earliest in a, and of all those maximal matching blocks that
@@ -393,12 +397,12 @@ func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode {
 	if codes[0].Tag == 'e' {
 		c := codes[0]
 		i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
-		codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2}
+		codes[0] = OpCode{c.Tag, maxInt(i1, i2-n), i2, maxInt(j1, j2-n), j2}
 	}
 	if codes[len(codes)-1].Tag == 'e' {
 		c := codes[len(codes)-1]
 		i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
-		codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)}
+		codes[len(codes)-1] = OpCode{c.Tag, i1, minInt(i2, i1+n), j1, minInt(j2, j1+n)}
 	}
 	nn := n + n
 	groups := [][]OpCode{}
@@ -408,11 +412,11 @@ func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode {
 		// End the current group and start a new one whenever
 		// there is a large range with no changes.
 		if c.Tag == 'e' && i2-i1 > nn {
-			group = append(group, OpCode{c.Tag, i1, min(i2, i1+n),
-				j1, min(j2, j1+n)})
+			group = append(group, OpCode{c.Tag, i1, minInt(i2, i1+n),
+				j1, minInt(j2, j1+n)})
 			groups = append(groups, group)
 			group = []OpCode{}
-			i1, j1 = max(i1, i2-n), max(j1, j2-n)
+			i1, j1 = maxInt(i1, i2-n), maxInt(j1, j2-n)
 		}
 		group = append(group, OpCode{c.Tag, i1, i2, j1, j2})
 	}
diff --git a/vendor/gotest.tools/v3/internal/source/bazel.go b/vendor/gotest.tools/v3/internal/source/bazel.go
new file mode 100644
index 00000000000..1f5197ddfc6
--- /dev/null
+++ b/vendor/gotest.tools/v3/internal/source/bazel.go
@@ -0,0 +1,51 @@
+package source
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+)
+
+// These Bazel env vars are documented here:
+// https://bazel.build/reference/test-encyclopedia
+
+// Signifies test executable is being driven by `bazel test`.
+//
+// Due to Bazel's compilation and sandboxing strategy,
+// some care is required to handle resolving the original *.go source file.
+var inBazelTest = os.Getenv("BAZEL_TEST") == "1"
+
+// The name of the target being tested (ex: //some_package:some_package_test)
+var bazelTestTarget = os.Getenv("TEST_TARGET")
+
+// Absolute path to the base of the runfiles tree
+var bazelTestSrcdir = os.Getenv("TEST_SRCDIR")
+
+// The local repository's workspace name (ex: __main__)
+var bazelTestWorkspace = os.Getenv("TEST_WORKSPACE")
+
+func bazelSourcePath(filename string) (string, error) {
+	// Use the env vars to resolve the test source files,
+	// which must be provided as test data in the respective go_test target.
+	filename = filepath.Join(bazelTestSrcdir, bazelTestWorkspace, filename)
+
+	_, err := os.Stat(filename)
+	if os.IsNotExist(err) {
+		return "", fmt.Errorf(bazelMissingSourceMsg, filename, bazelTestTarget)
+	}
+	return filename, nil
+}
+
+var bazelMissingSourceMsg = `
+the test source file does not exist: %s
+It appears that you are running this test under Bazel (target: %s).
+Check that your test source files are added as test data in your go_test targets.
+
+Example:
+    go_test(
+        name = "your_package_test",
+        srcs = ["your_test.go"],
+        deps = ["@tools_gotest_v3//assert"],
+        data = glob(["*_test.go"])
+    )"
+`
diff --git a/vendor/gotest.tools/v3/internal/source/source.go b/vendor/gotest.tools/v3/internal/source/source.go
index a4fc24ee63e..9ac4bfa7d11 100644
--- a/vendor/gotest.tools/v3/internal/source/source.go
+++ b/vendor/gotest.tools/v3/internal/source/source.go
@@ -10,6 +10,7 @@ import (
 	"go/parser"
 	"go/token"
 	"os"
+	"path/filepath"
 	"runtime"
 )
 
@@ -35,6 +36,19 @@ func CallExprArgs(stackIndex int) ([]ast.Expr, error) {
 	}
 	debug("call stack position: %s:%d", filename, line)
 
+	// Normally, `go` will compile programs with absolute paths in
+	// the debug metadata. However, in the name of reproducibility,
+	// Bazel uses a compilation strategy that results in relative paths
+	// (otherwise, since Bazel uses a random tmp dir for compile and sandboxing,
+	// the resulting binaries would change across compiles/test runs).
+	if inBazelTest && !filepath.IsAbs(filename) {
+		var err error
+		filename, err = bazelSourcePath(filename)
+		if err != nil {
+			return nil, err
+		}
+	}
+
 	fileset := token.NewFileSet()
 	astFile, err := parser.ParseFile(fileset, filename, nil, parser.AllErrors)
 	if err != nil {
@@ -58,7 +72,7 @@ func getNodeAtLine(fileset *token.FileSet, astFile ast.Node, lineNum int) (ast.N
 			return node, err
 		}
 	}
-	return nil, nil
+	return nil, errors.New("failed to find expression")
 }
 
 func scanToLine(fileset *token.FileSet, node ast.Node, lineNum int) ast.Node {
@@ -78,11 +92,8 @@ func scanToLine(fileset *token.FileSet, node ast.Node, lineNum int) ast.Node {
 
 func getCallExprArgs(fileset *token.FileSet, astFile ast.Node, line int) ([]ast.Expr, error) {
 	node, err := getNodeAtLine(fileset, astFile, line)
-	switch {
-	case err != nil:
+	if err != nil {
 		return nil, err
-	case node == nil:
-		return nil, fmt.Errorf("failed to find an expression")
 	}
 
 	debug("found node: %s", debugFormatNode{node})
@@ -90,7 +101,7 @@ func getCallExprArgs(fileset *token.FileSet, astFile ast.Node, line int) ([]ast.
 	visitor := &callExprVisitor{}
 	ast.Walk(visitor, node)
 	if visitor.expr == nil {
-		return nil, errors.New("failed to find call expression")
+		return nil, errors.New("failed to find an expression")
 	}
 	debug("callExpr: %s", debugFormatNode{visitor.expr})
 	return visitor.expr.Args, nil