66package cli
77
88import (
9+ "bytes"
910 "errors"
11+ "fmt"
1012 "os"
1113 "path/filepath"
14+ "strings"
1215 "testing"
1316
1417 "github.com/cockroachdb/cockroach/pkg/base"
1518 "github.com/cockroachdb/cockroach/pkg/cli/clierror"
1619 "github.com/cockroachdb/cockroach/pkg/cli/exit"
1720 "github.com/cockroachdb/cockroach/pkg/server"
1821 "github.com/cockroachdb/cockroach/pkg/testutils"
22+ "github.com/cockroachdb/cockroach/pkg/util/humanizeutil"
1923 "github.com/cockroachdb/cockroach/pkg/util/leaktest"
2024 "github.com/cockroachdb/cockroach/pkg/util/log"
2125 "github.com/cockroachdb/cockroach/pkg/util/netutil/addr"
26+ "github.com/cockroachdb/crlib/crstrings"
27+ "github.com/cockroachdb/datadriven"
2228 "github.com/cockroachdb/pebble/vfs"
2329 "github.com/stretchr/testify/require"
2430)
@@ -215,9 +221,8 @@ func TestExitIfDiskFull(t *testing.T) {
215221 defer leaktest .AfterTest (t )()
216222 defer log .Scope (t ).Close (t )
217223
218- err := exitIfDiskFull (mockDiskSpaceFS {FS : vfs .NewMem ()}, []base.StoreSpec {
219- {},
220- })
224+ err := exitIfDiskFull (t .Context (), & mockDiskSpaceFS {FS : vfs .NewMem ()},
225+ []base.StoreSpec {{}})
221226 require .Error (t , err )
222227 var cliErr * clierror.Error
223228 require .True (t , errors .As (err , & cliErr ))
@@ -226,12 +231,88 @@ func TestExitIfDiskFull(t *testing.T) {
226231
227232type mockDiskSpaceFS struct {
228233 vfs.FS
234+ diskUsages map [string ]vfs.DiskUsage
229235}
230236
231- func (fs mockDiskSpaceFS ) GetDiskUsage (path string ) (vfs.DiskUsage , error ) {
237+ func (fs * mockDiskSpaceFS ) Unwrap () vfs.FS { return fs .FS }
238+
239+ func (fs * mockDiskSpaceFS ) GetDiskUsage (path string ) (vfs.DiskUsage , error ) {
240+ if fs .diskUsages != nil {
241+ for usagePath , usage := range fs .diskUsages {
242+ if strings .HasPrefix (path , usagePath ) {
243+ return usage , nil
244+ }
245+ }
246+ }
232247 return vfs.DiskUsage {
233248 AvailBytes : 10 << 20 ,
234249 TotalBytes : 100 << 30 ,
235250 UsedBytes : 100 << 30 - 10 << 20 ,
236251 }, nil
237252}
253+
254+ func TestExitIfDiskFullDatadriven (t * testing.T ) {
255+ defer leaktest .AfterTest (t )()
256+ defer log .Scope (t ).Close (t )
257+
258+ var buf bytes.Buffer
259+ var fs vfs.FS = vfs .NewMem ()
260+ require .NoError (t , fs .MkdirAll ("/mnt" , 0755 ))
261+ mockDiskUsage := & mockDiskSpaceFS {FS : fs , diskUsages : make (map [string ]vfs.DiskUsage )}
262+ fs = vfs .WithLogging (mockDiskUsage , func (format string , args ... interface {}) {
263+ fmt .Fprint (& buf , "# " )
264+ fmt .Fprintf (& buf , format , args ... )
265+ fmt .Fprintln (& buf )
266+ })
267+ datadriven .RunTestAny (t , "testdata/exit_if_disk_full" , func (t testing.TB , td * datadriven.TestData ) string {
268+ buf .Reset ()
269+ switch td .Cmd {
270+ case "run" :
271+ var specs []base.StoreSpec
272+ clear (mockDiskUsage .diskUsages )
273+ for _ , line := range crstrings .Lines (td .Input ) {
274+ switch {
275+ case strings .HasPrefix (line , "disk-usage:" ):
276+ // disk-usage: <path> <avail> <total>
277+ line = strings .TrimSpace (strings .TrimPrefix (line , "disk-usage:" ))
278+ fields := strings .Fields (line )
279+ if len (fields ) != 3 {
280+ return fmt .Sprintf ("invalid disk-usage line: %q" , line )
281+ }
282+ path := fields [0 ]
283+ avail , err := humanizeutil .ParseBytes (fields [1 ])
284+ if err != nil {
285+ return fmt .Sprintf ("invalid disk-usage line: %q" , line )
286+ }
287+ total , err := humanizeutil .ParseBytes (fields [2 ])
288+ if err != nil {
289+ return fmt .Sprintf ("invalid disk-usage line: %q" , line )
290+ }
291+ mockDiskUsage .diskUsages [path ] = vfs.DiskUsage {
292+ AvailBytes : uint64 (avail ),
293+ TotalBytes : uint64 (total ),
294+ UsedBytes : uint64 (total - avail ),
295+ }
296+ case strings .HasPrefix (line , "store:" ):
297+ line = strings .TrimSpace (strings .TrimPrefix (line , "store:" ))
298+ spec , err := base .NewStoreSpec (line )
299+ if err != nil {
300+ return fmt .Sprintf ("failed to parse store spec: %v" , err )
301+ }
302+ specs = append (specs , spec )
303+ default :
304+ return fmt .Sprintf ("unknown line: %q" , line )
305+ }
306+ }
307+ err := exitIfDiskFull (t .Context (), fs , specs )
308+ if err == nil {
309+ fmt .Fprint (& buf , "<no-error>" )
310+ } else {
311+ fmt .Fprintf (& buf , "<error:%s>" , err )
312+ }
313+ return buf .String ()
314+ default :
315+ return fmt .Sprintf ("unknown command: %s" , td .Cmd )
316+ }
317+ })
318+ }
0 commit comments