diff --git a/internal/librarian/java/readme.go b/internal/librarian/java/readme.go index 15a0ce22606..8ca97817b8f 100644 --- a/internal/librarian/java/readme.go +++ b/internal/librarian/java/readme.go @@ -37,6 +37,9 @@ var ( // errEmptyTitle indicates the extracted title value is empty. errEmptyTitle = errors.New("title value cannot be empty") + + // errEmptyDir indicates the provided directory path is empty. + errEmptyDir = errors.New("dir cannot be empty") ) // codeSample represents a discovered Java code sample along with its derived title. @@ -45,6 +48,27 @@ type codeSample struct { File string } +// extractSamples locates production Java sample files and returns parsed codeSample structs +// containing display titles and relative paths for README rendering. +func extractSamples(dir string) ([]codeSample, error) { + if dir == "" { + return nil, errEmptyDir + } + files, err := collectSampleFiles(dir) + if err != nil { + return nil, err + } + var samples []codeSample + for _, file := range files { + sample, err := parseCodeSample(dir, file) + if err != nil { + return nil, err + } + samples = append(samples, *sample) + } + return samples, nil +} + // collectSampleFiles recursively scans dir/samples for Java production files. func collectSampleFiles(dir string) ([]string, error) { samplesDir := filepath.Join(dir, "samples") diff --git a/internal/librarian/java/readme_test.go b/internal/librarian/java/readme_test.go index d4ba75a3355..ea83f04e1d4 100644 --- a/internal/librarian/java/readme_test.go +++ b/internal/librarian/java/readme_test.go @@ -23,6 +23,127 @@ import ( "github.com/google/go-cmp/cmp" ) +func TestExtractSamples(t *testing.T) { + for _, test := range []struct { + name string + setupFiles func(t *testing.T, dir string) + want []codeSample + }{ + { + name: "missing samples directory", + setupFiles: func(t *testing.T, dir string) { + // Do nothing, tempDir is empty. + }, + want: nil, + }, + { + name: "extract successfully", + setupFiles: func(t *testing.T, dir string) { + samplesDir := filepath.Join(dir, "samples", "src", "main", "java") + if err := os.MkdirAll(samplesDir, 0755); err != nil { + t.Fatal(err) + } + file1 := filepath.Join(samplesDir, "RequesterPays.java") + content1 := `// sample-metadata: +// title: Custom Title Override +public class RequesterPays {}` + if err := os.WriteFile(file1, []byte(content1), 0644); err != nil { + t.Fatal(err) + } + file2 := filepath.Join(samplesDir, "DemoSample.java") + content2 := `public class DemoSample {}` + if err := os.WriteFile(file2, []byte(content2), 0644); err != nil { + t.Fatal(err) + } + }, + want: []codeSample{ + { + Title: "Demo Sample", + File: "samples/src/main/java/DemoSample.java", + }, + { + Title: "Custom Title Override", + File: "samples/src/main/java/RequesterPays.java", + }, + }, + }, + } { + t.Run(test.name, func(t *testing.T) { + tempDir := t.TempDir() + test.setupFiles(t, tempDir) + + samples, err := extractSamples(tempDir) + if err != nil { + t.Fatal(err) + } + if diff := cmp.Diff(test.want, samples); diff != "" { + t.Errorf("mismatch (-want +got):\n%s", diff) + } + }) + } +} + +func TestExtractSamples_Error(t *testing.T) { + for _, test := range []struct { + name string + setupFiles func(t *testing.T, dir string) + dir string + wantErr error + }{ + { + name: "error on empty directory", + dir: "", + wantErr: errEmptyDir, + }, + { + name: "error on empty title override", + setupFiles: func(t *testing.T, dir string) { + samplesDir := filepath.Join(dir, "samples", "src", "main", "java") + if err := os.MkdirAll(samplesDir, 0755); err != nil { + t.Fatal(err) + } + file := filepath.Join(samplesDir, "Sample.java") + content := `// sample-metadata: +// title: "" +public class Invalid {}` + if err := os.WriteFile(file, []byte(content), 0644); err != nil { + t.Fatal(err) + } + }, + wantErr: errEmptyTitle, + }, + { + name: "error on missing title line immediately following sample-metadata", + setupFiles: func(t *testing.T, dir string) { + samplesDir := filepath.Join(dir, "samples", "src", "main", "java") + if err := os.MkdirAll(samplesDir, 0755); err != nil { + t.Fatal(err) + } + file := filepath.Join(samplesDir, "Sample.java") + content := `// sample-metadata: +// description: missing title line +public class Invalid {}` + if err := os.WriteFile(file, []byte(content), 0644); err != nil { + t.Fatal(err) + } + }, + wantErr: errMissingTitle, + }, + } { + t.Run(test.name, func(t *testing.T) { + dir := test.dir + if test.setupFiles != nil { + dir = t.TempDir() + test.setupFiles(t, dir) + } + _, err := extractSamples(dir) + if !errors.Is(err, test.wantErr) { + t.Errorf("extractSamples() err = %v, want %v", err, test.wantErr) + } + }) + } +} + func TestCollectSampleFiles(t *testing.T) { for _, test := range []struct { name string