@@ -10,6 +10,7 @@ import (
1010 "net/http"
1111 "net/http/httptest"
1212 "os"
13+ "path/filepath"
1314 "strings"
1415 "testing"
1516
@@ -706,6 +707,34 @@ func TestServer_UploadFiles(t *testing.T) {
706707 expectedStatusCode : http .StatusOK ,
707708 expectFilePath : true ,
708709 },
710+ {
711+ name : "upload file with absolute path filename" ,
712+ filename : "/tmp/absolute-path-file.txt" ,
713+ fileContent : "absolute path content" ,
714+ expectedStatusCode : http .StatusOK ,
715+ expectFilePath : true ,
716+ },
717+ {
718+ name : "upload file with relative path filename" ,
719+ filename : "../relative-path-file.txt" ,
720+ fileContent : "relative path content" ,
721+ expectedStatusCode : http .StatusOK ,
722+ expectFilePath : true ,
723+ },
724+ {
725+ name : "upload file with nested relative path" ,
726+ filename : "nested/path/file.txt" ,
727+ fileContent : "nested content" ,
728+ expectedStatusCode : http .StatusOK ,
729+ expectFilePath : true ,
730+ },
731+ {
732+ name : "upload file with backslash path separators" ,
733+ filename : "windows\\ style\\ path.txt" ,
734+ fileContent : "windows path content" ,
735+ expectedStatusCode : http .StatusOK ,
736+ expectFilePath : true ,
737+ },
709738 }
710739
711740 for _ , tc := range cases {
@@ -766,8 +795,8 @@ func TestServer_UploadFiles(t *testing.T) {
766795 require .NoError (t , err )
767796 require .Equal (t , tc .fileContent , string (savedContent ), "file content should match" )
768797
769- // Verify filename is preserved in the path
770- expectedFilename := tc .filename
798+ // Verify filename is preserved in the path (only the base filename for security)
799+ expectedFilename := filepath . Base ( tc .filename )
771800 if expectedFilename == "" {
772801 expectedFilename = "uploaded_file"
773802 }
@@ -839,4 +868,91 @@ func TestServer_UploadFiles_Errors(t *testing.T) {
839868
840869 require .Equal (t , http .StatusUnprocessableEntity , resp .StatusCode )
841870 })
871+
872+ t .Run ("file size exactly 10MB" , func (t * testing.T ) {
873+ t .Parallel ()
874+
875+ // Create exactly 10MB of data
876+ const tenMB = 10 << 20
877+ fileContent := make ([]byte , tenMB )
878+ for i := range fileContent {
879+ fileContent [i ] = byte (i % 256 )
880+ }
881+
882+ var buf bytes.Buffer
883+ writer := multipart .NewWriter (& buf )
884+ part , err := writer .CreateFormFile ("file" , "10mb-file.bin" )
885+ require .NoError (t , err )
886+ _ , err = part .Write (fileContent )
887+ require .NoError (t , err )
888+ err = writer .Close ()
889+ require .NoError (t , err )
890+
891+ req , err := http .NewRequest ("POST" , tsServer .URL + "/upload" , & buf )
892+ require .NoError (t , err )
893+ req .Header .Set ("Content-Type" , writer .FormDataContentType ())
894+
895+ client := & http.Client {}
896+ resp , err := client .Do (req )
897+ require .NoError (t , err )
898+ t .Cleanup (func () {
899+ _ = resp .Body .Close ()
900+ })
901+
902+ require .Equal (t , http .StatusOK , resp .StatusCode )
903+
904+ // Parse response to get file path for cleanup
905+ body , err := io .ReadAll (resp .Body )
906+ require .NoError (t , err )
907+ var uploadResp struct {
908+ Ok bool `json:"ok"`
909+ FilePath string `json:"filePath"`
910+ }
911+ err = json .Unmarshal (body , & uploadResp )
912+ require .NoError (t , err )
913+ require .True (t , uploadResp .Ok )
914+
915+ // Clean up the uploaded file
916+ t .Cleanup (func () {
917+ _ = os .Remove (uploadResp .FilePath )
918+ })
919+ })
920+
921+ t .Run ("file size exceeds 10MB limit" , func (t * testing.T ) {
922+ t .Parallel ()
923+
924+ // Create slightly more than 10MB of data
925+ const tenMBPlusOne = (10 << 20 ) + 1
926+ fileContent := make ([]byte , tenMBPlusOne )
927+ for i := range fileContent {
928+ fileContent [i ] = byte (i % 256 )
929+ }
930+
931+ var buf bytes.Buffer
932+ writer := multipart .NewWriter (& buf )
933+ part , err := writer .CreateFormFile ("file" , "large-file.bin" )
934+ require .NoError (t , err )
935+ _ , err = part .Write (fileContent )
936+ require .NoError (t , err )
937+ err = writer .Close ()
938+ require .NoError (t , err )
939+
940+ req , err := http .NewRequest ("POST" , tsServer .URL + "/upload" , & buf )
941+ require .NoError (t , err )
942+ req .Header .Set ("Content-Type" , writer .FormDataContentType ())
943+
944+ client := & http.Client {}
945+ resp , err := client .Do (req )
946+ require .NoError (t , err )
947+ t .Cleanup (func () {
948+ _ = resp .Body .Close ()
949+ })
950+
951+ require .Equal (t , http .StatusBadRequest , resp .StatusCode )
952+
953+ // Verify error message
954+ body , err := io .ReadAll (resp .Body )
955+ require .NoError (t , err )
956+ require .Contains (t , string (body ), "file size exceeds 10MB limit" )
957+ })
842958}
0 commit comments