2026-10-26 02:59:28 +00:00
package commandkit
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"strings"
"testing"
)
func TestExecuteGivesEachInvocationItsReporterAndAppliesSelection ( t * testing . T ) {
var reporters [ ] * Reporter
command := NewCommand ( CommandSpec [ struct { } ] {
Name : "run" ,
Run : func ( inv Invocation , _ struct { } ) Outcome {
reporter := inv . Reporter ( )
reporters = append ( reporters , reporter )
if _ , err := fmt . Fprint ( reporter . Output ( ) , "result\n" ) ; err != nil {
t . Errorf ( "write result: %v" , err )
}
if err := reporter . Warn ( "attention" ) ; err != nil {
t . Errorf ( "submit warning: %v" , err )
}
return Outcome {
Kind : OutcomeDomain , Domain : "accepted" , Status : 0 ,
Presentation : PresentationResult {
Output : DeliveryResult { State : DeliveryIncomplete , WriteError : io . ErrClosedPipe } ,
} ,
}
} ,
} )
app , err := New ( Identity { Name : "Example" } , command )
if err != nil {
t . Fatal ( err )
}
var quietOut , quietErr bytes . Buffer
quiet := app . Execute ( context . Background ( ) , [ ] string { "run" , "--quiet" } , Streams { Out : & quietOut , Err : & quietErr } )
if quiet . Kind != OutcomeDomain || quiet . Status != 0 || quiet . Domain != "accepted" {
t . Fatalf ( "quiet outcome = %#v" , quiet )
}
if quietOut . Len ( ) != 0 || quietErr . Len ( ) != 0 {
t . Fatalf ( "quiet output = %q, diagnostics = %q" , quietOut . String ( ) , quietErr . String ( ) )
}
if quiet . Presentation . Output . State != DeliverySuppressed || quiet . Presentation . Diagnostics . State != DeliverySuppressed {
t . Fatalf ( "quiet presentation = %#v" , quiet . Presentation )
}
var verboseOut , verboseErr bytes . Buffer
verbose := app . Execute ( context . Background ( ) , [ ] string { "run" , "--verbose" } , Streams { Out : & verboseOut , Err : & verboseErr } )
if verbose . Kind != OutcomeDomain || verbose . Status != 0 {
t . Fatalf ( "verbose outcome = %#v" , verbose )
}
if verboseOut . String ( ) != "result\n" || verboseErr . String ( ) != "WARN: attention\n" {
t . Fatalf ( "verbose output = %q, diagnostics = %q" , verboseOut . String ( ) , verboseErr . String ( ) )
}
if verbose . Presentation . Output . State != DeliveryComplete || verbose . Presentation . Diagnostics . State != DeliveryComplete {
t . Fatalf ( "verbose presentation = %#v" , verbose . Presentation )
}
if len ( reporters ) != 2 || reporters [ 0 ] == nil || reporters [ 1 ] == nil || reporters [ 0 ] == reporters [ 1 ] {
t . Fatalf ( "invocation reporters = %#v" , reporters )
}
if _ , err := reporters [ 0 ] . Output ( ) . Write ( [ ] byte ( "late" ) ) ; ! errors . Is ( err , ErrReporterClosed ) {
t . Fatalf ( "write through finalized reporter error = %v" , err )
}
}
func TestExecuteQuietUsageKeepsAliasGuidanceVisible ( t * testing . T ) {
command := NewCommand ( CommandSpec [ struct { } ] {
Name : "run" ,
Run : func ( Invocation , struct { } ) Outcome { return Success ( ) } ,
} )
app , err := New ( Identity { Name : "Example" } , command , Alias ( "r" , "run" ) )
if err != nil {
t . Fatal ( err )
}
var output , diagnostics bytes . Buffer
outcome := app . Execute ( context . Background ( ) , [ ] string { "r" , "--quiet" , "--unknown" } , Streams { Out : & output , Err : & diagnostics } )
if outcome . Kind != OutcomeUsage || outcome . Status != 2 {
t . Fatalf ( "outcome = %#v" , outcome )
}
if output . Len ( ) != 0 {
t . Fatalf ( "usage output = %q" , output . String ( ) )
}
if got := diagnostics . String ( ) ; ! strings . Contains ( got , "ERROR: unknown flag" ) || ! strings . Contains ( got , "Usage: Example r" ) || ! strings . Contains ( got , "Alias for: Example run" ) {
t . Fatalf ( "usage diagnostics = %q" , got )
}
if outcome . Presentation . Diagnostics . State != DeliveryComplete {
t . Fatalf ( "diagnostic presentation = %#v" , outcome . Presentation . Diagnostics )
}
}
2026-10-26 14:33:31 +00:00
func TestUnresolvedRoutesUseReportingAliasesForTheirParseContext ( t * testing . T ) {
calls := 0
command := NewCommand ( CommandSpec [ struct { } ] {
Name : "run" ,
NewInput : func ( ) struct { } { calls ++ ; return struct { } { } } ,
Run : func ( Invocation , struct { } ) Outcome { calls ++ ; return Success ( ) } ,
} )
app , err := New ( Identity { Name : "Example" } , Group ( "group" , "" , Group ( "nested" , "" , command ) ) ,
FlagAlias ( "-d" , "--debug" ) , FlagAlias ( "-q" , "--quiet" ) ,
FlagAlias ( "-x" , "--quiet" ) , FlagAliasFor ( "group nested" , "-x" , "--debug" ) )
if err != nil {
t . Fatal ( err )
}
for _ , path := range [ ] [ ] string { { "missing" } , { "group" , "missing" } , { "group" , "nested" , "missing" } } {
t . Run ( strings . Join ( path , "/" ) , func ( t * testing . T ) {
var canonicalDiagnostics , aliasDiagnostics bytes . Buffer
canonical := app . Execute ( context . Background ( ) , append ( append ( [ ] string ( nil ) , path ... ) , "--debug" ) , Streams { Err : & canonicalDiagnostics } )
alias := app . Execute ( context . Background ( ) , append ( append ( [ ] string ( nil ) , path ... ) , "-d" ) , Streams { Err : & aliasDiagnostics } )
if canonical . Kind != OutcomeUsage || alias . Kind != OutcomeUsage || canonical . Status != alias . Status || canonical . Explanation . Message != alias . Explanation . Message {
t . Fatalf ( "canonical=%#v alias=%#v" , canonical , alias )
}
for _ , text := range [ ] string { canonicalDiagnostics . String ( ) , aliasDiagnostics . String ( ) } {
if ! strings . Contains ( text , "DEBUG:" ) || ! strings . Contains ( text , "ERROR:" ) || strings . Contains ( text , "unknown shorthand" ) || strings . Contains ( text , "Alias for:" ) {
t . Fatalf ( "diagnostics=%q" , text )
}
}
route := resolveEnteredRoute ( path , app . routeSnapshot ( ) )
if route . kind != routeUnknown || len ( route . canonicalPath ) != 0 {
t . Fatalf ( "invalid route acquired canonical identity: %#v" , route )
}
var quiet bytes . Buffer
got := app . Execute ( context . Background ( ) , append ( append ( [ ] string ( nil ) , path ... ) , "-q" , "--unknown" ) , Streams { Err : & quiet } )
if got . Kind != OutcomeUsage || ! strings . Contains ( quiet . String ( ) , "ERROR: unknown flag" ) || strings . Contains ( quiet . String ( ) , "DEBUG:" ) {
t . Fatalf ( "quiet alias outcome=%#v diagnostics=%q" , got , quiet . String ( ) )
}
} )
}
var scoped bytes . Buffer
got := app . Execute ( context . Background ( ) , [ ] string { "group" , "nested" , "missing" , "-x" } , Streams { Err : & scoped } )
if got . Kind != OutcomeUsage || ! strings . Contains ( scoped . String ( ) , "DEBUG:" ) {
t . Fatalf ( "scoped precedence outcome=%#v diagnostics=%q" , got , scoped . String ( ) )
}
if calls != 0 {
t . Fatalf ( "invalid routes ran factories or handlers %d times" , calls )
}
}
2026-10-26 02:59:28 +00:00
type executeReportingFailureWriter struct { err error }
func ( w executeReportingFailureWriter ) Write ( [ ] byte ) ( int , error ) { return 0 , w . err }
func TestExecuteFinalizesEarlyAndIgnoredWriterFailures ( t * testing . T ) {
command := NewCommand ( CommandSpec [ struct { } ] {
Name : "run" ,
Run : func ( inv Invocation , _ struct { } ) Outcome {
_ , _ = inv . Reporter ( ) . Output ( ) . Write ( [ ] byte ( "report" ) )
return Success ( )
} ,
} )
app , err := New ( Identity { Name : "Example" } , command )
if err != nil {
t . Fatal ( err )
}
writeErr := errors . New ( "result destination failed" )
var diagnostics bytes . Buffer
outcome := app . Execute ( context . Background ( ) , [ ] string { "run" } , Streams {
Out : executeReportingFailureWriter { err : writeErr } , Err : & diagnostics ,
} )
if outcome . Kind != OutcomeOperational || outcome . Status != 1 || ! errors . Is ( outcome . Presentation . Output . WriteError , writeErr ) {
t . Fatalf ( "ignored output failure outcome = %#v" , outcome )
}
2026-10-26 14:28:58 +00:00
if ! strings . Contains ( diagnostics . String ( ) , "deliver" ) || ! strings . Contains ( diagnostics . String ( ) , "output" ) {
2026-10-26 02:59:28 +00:00
t . Fatalf ( "fallback diagnostic = %q" , diagnostics . String ( ) )
}
diagnostics . Reset ( )
outcome = app . Execute ( nil , [ ] string { "run" } , Streams { Err : & diagnostics } )
if outcome . Kind != OutcomeOperational || outcome . Status != 1 || outcome . Cause == nil {
t . Fatalf ( "nil context outcome = %#v" , outcome )
}
if ! strings . Contains ( diagnostics . String ( ) , "ERROR: invocation context must not be nil\n" ) {
t . Fatalf ( "nil context diagnostic = %q" , diagnostics . String ( ) )
}
diagnostics . Reset ( )
var nilApp * App
outcome = nilApp . Execute ( context . Background ( ) , [ ] string { "run" } , Streams { Err : & diagnostics } )
if outcome . Kind != OutcomeOperational || outcome . Status != 1 || outcome . Cause == nil {
t . Fatalf ( "nil app outcome = %#v" , outcome )
}
if ! strings . Contains ( diagnostics . String ( ) , "ERROR: cannot execute commands on a nil app\n" ) {
t . Fatalf ( "nil app diagnostic = %q" , diagnostics . String ( ) )
}
}