@@ -1194,6 +1194,176 @@ func createHashSet(items []string) *hashset.Set {
11941194 return set
11951195}
11961196
1197+ // TestModelfileWithSpacesInPaths tests handling of file paths containing spaces
1198+ func TestModelfileWithSpacesInPaths (t * testing.T ) {
1199+ // Test case 1: Create a modelfile with paths containing spaces
1200+ tempDir , err := os .MkdirTemp ("" , "spaces-test-*" )
1201+ require .NoError (t , err )
1202+ defer os .RemoveAll (tempDir )
1203+
1204+ // Create files with spaces in their names
1205+ filesWithSpaces := map [string ]string {
1206+ "config file.json" : `{"model_type": "test"}` ,
1207+ "model weights.bin" : "model content" ,
1208+ "inference script.py" : "print('hello')" ,
1209+ "README file.md" : "# Documentation" ,
1210+ "nested dir/config.json" : `{"test": true}` ,
1211+ "path with/spaces here/model.safetensors" : "model data" ,
1212+ }
1213+
1214+ // Create directories
1215+ err = os .MkdirAll (filepath .Join (tempDir , "nested dir" ), 0755 )
1216+ require .NoError (t , err )
1217+ err = os .MkdirAll (filepath .Join (tempDir , "path with" , "spaces here" ), 0755 )
1218+ require .NoError (t , err )
1219+
1220+ // Create files
1221+ for filename , content := range filesWithSpaces {
1222+ fullPath := filepath .Join (tempDir , filename )
1223+ err = os .WriteFile (fullPath , []byte (content ), 0644 )
1224+ require .NoError (t , err )
1225+ }
1226+
1227+ // Generate modelfile using workspace
1228+ config := & configmodelfile.GenerateConfig {
1229+ Name : "spaces-test" ,
1230+ }
1231+
1232+ mf , err := NewModelfileByWorkspace (tempDir , config )
1233+ require .NoError (t , err )
1234+
1235+ // Get the generated modelfile content
1236+ content := mf .Content ()
1237+ contentStr := string (content )
1238+
1239+ // Print the content for debugging
1240+ t .Logf ("Generated Modelfile content:\n %s" , contentStr )
1241+
1242+ // Test case 2: Try to parse the generated modelfile
1243+ modelfileContent := contentStr
1244+
1245+ // Write the content to a temporary file
1246+ tempModelfile , err := os .CreateTemp ("" , "Modelfile-*" )
1247+ require .NoError (t , err )
1248+ defer os .Remove (tempModelfile .Name ())
1249+
1250+ _ , err = tempModelfile .WriteString (modelfileContent )
1251+ require .NoError (t , err )
1252+ err = tempModelfile .Close ()
1253+ require .NoError (t , err )
1254+
1255+ // Try to parse the modelfile back
1256+ parsedMf , err := NewModelfile (tempModelfile .Name ())
1257+ if err != nil {
1258+ t .Logf ("Error parsing modelfile with spaces: %v" , err )
1259+ t .Logf ("Modelfile content that failed to parse:\n %s" , modelfileContent )
1260+ }
1261+ require .NoError (t , err , "Should be able to parse modelfile with spaces in paths" )
1262+
1263+ // Verify that the parsed modelfile contains the expected files
1264+ configs := parsedMf .GetConfigs ()
1265+ models := parsedMf .GetModels ()
1266+ codes := parsedMf .GetCodes ()
1267+ docs := parsedMf .GetDocs ()
1268+
1269+ // Check that files with spaces are properly handled
1270+ allFiles := append (append (append (configs , models ... ), codes ... ), docs ... )
1271+
1272+ expectedFiles := []string {
1273+ "config file.json" ,
1274+ "model weights.bin" ,
1275+ "inference script.py" ,
1276+ "README file.md" ,
1277+ "nested dir/config.json" ,
1278+ "path with/spaces here/model.safetensors" ,
1279+ }
1280+
1281+ for _ , expectedFile := range expectedFiles {
1282+ found := false
1283+ for _ , file := range allFiles {
1284+ if file == expectedFile {
1285+ found = true
1286+ break
1287+ }
1288+ }
1289+ assert .True (t , found , "Expected file '%s' should be found in parsed modelfile" , expectedFile )
1290+ }
1291+ }
1292+
1293+ // TestModelfileParsingWithQuotedPaths tests parsing of modelfile with quoted paths
1294+ func TestModelfileParsingWithQuotedPaths (t * testing.T ) {
1295+ testCases := []struct {
1296+ name string
1297+ content string
1298+ expectError bool
1299+ description string
1300+ }{
1301+ {
1302+ name : "unquoted_paths_with_spaces" ,
1303+ content : `# Test modelfile
1304+ NAME test-model
1305+ CONFIG config file.json
1306+ MODEL model weights.bin
1307+ CODE inference script.py
1308+ DOC README file.md
1309+ ` ,
1310+ expectError : true ,
1311+ description : "Unquoted paths with spaces should cause parsing errors" ,
1312+ },
1313+ {
1314+ name : "quoted_paths_with_spaces" ,
1315+ content : `# Test modelfile
1316+ NAME test-model
1317+ CONFIG "config file.json"
1318+ MODEL "model weights.bin"
1319+ CODE "inference script.py"
1320+ DOC "README file.md"
1321+ ` ,
1322+ expectError : false ,
1323+ description : "Quoted paths with spaces should parse correctly" ,
1324+ },
1325+ {
1326+ name : "mixed_quoted_unquoted" ,
1327+ content : `# Test modelfile
1328+ NAME test-model
1329+ CONFIG config.json
1330+ MODEL "model weights.bin"
1331+ CODE script.py
1332+ DOC "README file.md"
1333+ ` ,
1334+ expectError : false ,
1335+ description : "Mix of quoted and unquoted paths should work" ,
1336+ },
1337+ }
1338+
1339+ for _ , tc := range testCases {
1340+ t .Run (tc .name , func (t * testing.T ) {
1341+ // Create temporary modelfile
1342+ tempFile , err := os .CreateTemp ("" , "modelfile-test-*" )
1343+ require .NoError (t , err )
1344+ defer os .Remove (tempFile .Name ())
1345+
1346+ _ , err = tempFile .WriteString (tc .content )
1347+ require .NoError (t , err )
1348+ err = tempFile .Close ()
1349+ require .NoError (t , err )
1350+
1351+ // Try to parse
1352+ mf , err := NewModelfile (tempFile .Name ())
1353+
1354+ if tc .expectError {
1355+ assert .Error (t , err , tc .description )
1356+ } else {
1357+ assert .NoError (t , err , tc .description )
1358+ if err == nil {
1359+ // Verify content is parsed correctly
1360+ assert .Equal (t , "test-model" , mf .GetName ())
1361+ }
1362+ }
1363+ })
1364+ }
1365+ }
1366+
11971367// TestGenerateByModelConfig tests the generateByModelConfig method
11981368func TestGenerateByModelConfig (t * testing.T ) {
11991369 testcases := []struct {
0 commit comments