@@ -692,3 +692,215 @@ func TestOffsetWriter_Write(t *testing.T) {
692692 checkContent (name , f )
693693 })
694694}
695+
696+ var errLimit = errors .New ("limit exceeded" )
697+
698+ func TestLimitedReader (t * testing.T ) {
699+ src := strings .NewReader ("abc" )
700+ r := LimitReader (src , 5 )
701+ lr , ok := r .(* LimitedReader )
702+ if ! ok {
703+ t .Fatalf ("LimitReader should return *LimitedReader, got %T" , r )
704+ }
705+ if lr .R != src || lr .N != 5 || lr .Err != nil {
706+ t .Fatalf ("LimitReader() = {R: %v, N: %d, Err: %v}, want {R: %v, N: 5, Err: nil}" , lr .R , lr .N , lr .Err , src )
707+ }
708+
709+ t .Run ("WithoutCustomErr" , func (t * testing.T ) {
710+ tests := []struct {
711+ name string
712+ data string
713+ limit int64
714+ want1N int
715+ want1E error
716+ want2E error
717+ }{
718+ {"UnderLimit" , "hello" , 10 , 5 , nil , EOF },
719+ {"ExactLimit" , "hello" , 5 , 5 , nil , EOF },
720+ {"OverLimit" , "hello world" , 5 , 5 , nil , EOF },
721+ {"ZeroLimit" , "hello" , 0 , 0 , EOF , EOF },
722+ }
723+
724+ for _ , tt := range tests {
725+ t .Run (tt .name , func (t * testing.T ) {
726+ lr := & LimitedReader {R : strings .NewReader (tt .data ), N : tt .limit }
727+ buf := make ([]byte , 10 )
728+
729+ n , err := lr .Read (buf )
730+ if n != tt .want1N || err != tt .want1E {
731+ t .Errorf ("first Read() = (%d, %v), want (%d, %v)" , n , err , tt .want1N , tt .want1E )
732+ }
733+
734+ n , err = lr .Read (buf )
735+ if n != 0 || err != tt .want2E {
736+ t .Errorf ("second Read() = (%d, %v), want (0, %v)" , n , err , tt .want2E )
737+ }
738+ })
739+ }
740+ })
741+
742+ t .Run ("WithCustomErr" , func (t * testing.T ) {
743+ tests := []struct {
744+ name string
745+ data string
746+ limit int64
747+ err error
748+ wantFirst string
749+ wantErr1 error
750+ wantErr2 error
751+ }{
752+ {"ExactLimit" , "hello" , 5 , errLimit , "hello" , nil , EOF },
753+ {"OverLimit" , "hello world" , 5 , errLimit , "hello" , nil , errLimit },
754+ {"UnderLimit" , "hi" , 5 , errLimit , "hi" , nil , EOF },
755+ {"ZeroLimitEmpty" , "" , 0 , errLimit , "" , EOF , EOF },
756+ {"ZeroLimitNonEmpty" , "hello" , 0 , errLimit , "" , errLimit , errLimit },
757+ }
758+
759+ for _ , tt := range tests {
760+ t .Run (tt .name , func (t * testing.T ) {
761+ lr := & LimitedReader {R : strings .NewReader (tt .data ), N : tt .limit , Err : tt .err }
762+ buf := make ([]byte , 10 )
763+
764+ n , err := lr .Read (buf )
765+ if n != len (tt .wantFirst ) || string (buf [:n ]) != tt .wantFirst || err != tt .wantErr1 {
766+ t .Errorf ("first Read() = (%d, %q, %v), want (%d, %q, %v)" , n , buf [:n ], err , len (tt .wantFirst ), tt .wantFirst , tt .wantErr1 )
767+ }
768+
769+ n , err = lr .Read (buf )
770+ if n != 0 || err != tt .wantErr2 {
771+ t .Errorf ("second Read() = (%d, %v), want (0, %v)" , n , err , tt .wantErr2 )
772+ }
773+ })
774+ }
775+ })
776+
777+ t .Run ("CustomErrPersists" , func (t * testing.T ) {
778+ lr := & LimitedReader {R : strings .NewReader ("hello world" ), N : 5 , Err : errLimit }
779+ buf := make ([]byte , 10 )
780+
781+ n , err := lr .Read (buf )
782+ if n != 5 || err != nil || string (buf [:5 ]) != "hello" {
783+ t .Errorf ("Read() = (%d, %v, %q), want (5, nil, \" hello\" )" , n , err , buf [:5 ])
784+ }
785+
786+ n , err = lr .Read (buf )
787+ if n != 0 || err != errLimit {
788+ t .Errorf ("Read() = (%d, %v), want (0, errLimit)" , n , err )
789+ }
790+
791+ n , err = lr .Read (buf )
792+ if n != 0 || err != errLimit {
793+ t .Errorf ("Read() = (%d, %v), want (0, errLimit)" , n , err )
794+ }
795+ })
796+
797+ t .Run ("ErrEOF" , func (t * testing.T ) {
798+ lr := & LimitedReader {R : strings .NewReader ("hello world" ), N : 5 , Err : EOF }
799+ buf := make ([]byte , 10 )
800+
801+ n , err := lr .Read (buf )
802+ if n != 5 || err != nil {
803+ t .Errorf ("Read() = (%d, %v), want (5, nil)" , n , err )
804+ }
805+
806+ n , err = lr .Read (buf )
807+ if n != 0 || err != EOF {
808+ t .Errorf ("Read() = (%d, %v), want (0, EOF)" , n , err )
809+ }
810+ })
811+
812+ t .Run ("NoSideEffects" , func (t * testing.T ) {
813+ lr := & LimitedReader {R : strings .NewReader ("hello" ), N : 5 , Err : errLimit }
814+ buf := make ([]byte , 0 )
815+
816+ for i := 0 ; i < 3 ; i ++ {
817+ n , err := lr .Read (buf )
818+ if n != 0 || err != nil {
819+ t .Errorf ("zero-length read #%d = (%d, %v), want (0, nil)" , i + 1 , n , err )
820+ }
821+ if lr .N != 5 {
822+ t .Errorf ("N after zero-length read #%d = %d, want 5" , i + 1 , lr .N )
823+ }
824+ }
825+
826+ buf = make ([]byte , 10 )
827+ n , err := lr .Read (buf )
828+ if n != 5 || string (buf [:5 ]) != "hello" || err != nil {
829+ t .Errorf ("normal Read() = (%d, %q, %v), want (5, \" hello\" , nil)" , n , buf [:5 ], err )
830+ }
831+ })
832+ }
833+
834+ type errorReader struct {
835+ data []byte
836+ pos int
837+ err error
838+ }
839+
840+ func (r * errorReader ) Read (p []byte ) (int , error ) {
841+ if r .pos >= len (r .data ) {
842+ return 0 , r .err
843+ }
844+ n := copy (p , r .data [r .pos :])
845+ r .pos += n
846+ return n , nil
847+ }
848+
849+ func TestLimitedReaderErrors (t * testing.T ) {
850+ t .Run ("UnderlyingError" , func (t * testing.T ) {
851+ underlyingErr := errors .New ("boom" )
852+ lr := & LimitedReader {R : & errorReader {data : []byte ("hello" ), err : underlyingErr }, N : 10 }
853+ buf := make ([]byte , 10 )
854+
855+ n , err := lr .Read (buf )
856+ if n != 5 || string (buf [:5 ]) != "hello" || err != nil {
857+ t .Errorf ("first Read() = (%d, %q, %v), want (5, \" hello\" , nil)" , n , buf [:5 ], err )
858+ }
859+
860+ n , err = lr .Read (buf )
861+ if n != 0 || err != underlyingErr {
862+ t .Errorf ("second Read() = (%d, %v), want (0, %v)" , n , err , underlyingErr )
863+ }
864+ })
865+
866+ t .Run ("SentinelMasksProbeError" , func (t * testing.T ) {
867+ probeErr := errors .New ("probe failed" )
868+ lr := & LimitedReader {R : & errorReader {data : []byte ("hello" ), err : probeErr }, N : 5 , Err : errLimit }
869+ buf := make ([]byte , 10 )
870+
871+ n , err := lr .Read (buf )
872+ if n != 5 || string (buf [:5 ]) != "hello" || err != nil {
873+ t .Errorf ("first Read() = (%d, %q, %v), want (5, \" hello\" , nil)" , n , buf [:5 ], err )
874+ }
875+
876+ n , err = lr .Read (buf )
877+ if n != 0 || err != errLimit {
878+ t .Errorf ("second Read() = (%d, %v), want (0, errLimit)" , n , err )
879+ }
880+ })
881+ }
882+
883+ func TestLimitedReaderCopy (t * testing.T ) {
884+ tests := []struct {
885+ name string
886+ input string
887+ limit int64
888+ wantN int64
889+ wantErr error
890+ }{
891+ {"Exact" , "hello" , 5 , 5 , nil },
892+ {"Under" , "hi" , 5 , 2 , nil },
893+ {"Over" , "hello world" , 5 , 5 , errLimit },
894+ }
895+
896+ for _ , tt := range tests {
897+ t .Run (tt .name , func (t * testing.T ) {
898+ lr := & LimitedReader {R : strings .NewReader (tt .input ), N : tt .limit , Err : errLimit }
899+ var dst Buffer
900+ n , err := Copy (& dst , lr )
901+ if n != tt .wantN || err != tt .wantErr {
902+ t .Errorf ("Copy() = (%d, %v), want (%d, %v)" , n , err , tt .wantN , tt .wantErr )
903+ }
904+ })
905+ }
906+ }
0 commit comments