github.com/nextlinux/gosbom@v0.81.1-0.20230627115839-1ff50c281391/gosbom/pkg/cataloger/java/parse_pom_xml_test.go (about)

     1  package java
     2  
     3  import (
     4  	"os"
     5  	"testing"
     6  
     7  	"github.com/nextlinux/gosbom/gosbom/file"
     8  	"github.com/nextlinux/gosbom/gosbom/pkg"
     9  	"github.com/nextlinux/gosbom/gosbom/pkg/cataloger/internal/pkgtest"
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/vifraa/gopom"
    12  )
    13  
    14  func Test_parserPomXML(t *testing.T) {
    15  	tests := []struct {
    16  		input    string
    17  		expected []pkg.Package
    18  	}{
    19  		{
    20  			input: "test-fixtures/pom/pom.xml",
    21  			expected: []pkg.Package{
    22  				{
    23  					Name:         "joda-time",
    24  					Version:      "2.9.2",
    25  					PURL:         "pkg:maven/com.joda/joda-time@2.9.2",
    26  					Language:     pkg.Java,
    27  					Type:         pkg.JavaPkg,
    28  					MetadataType: pkg.JavaMetadataType,
    29  					Metadata: pkg.JavaMetadata{
    30  						PomProperties: &pkg.PomProperties{
    31  							GroupID:    "com.joda",
    32  							ArtifactID: "joda-time",
    33  						},
    34  					},
    35  				},
    36  				{
    37  					Name:         "junit",
    38  					Version:      "4.12",
    39  					PURL:         "pkg:maven/junit/junit@4.12",
    40  					Language:     pkg.Java,
    41  					Type:         pkg.JavaPkg,
    42  					MetadataType: pkg.JavaMetadataType,
    43  					Metadata: pkg.JavaMetadata{
    44  						PomProperties: &pkg.PomProperties{
    45  							GroupID:    "junit",
    46  							ArtifactID: "junit",
    47  							Scope:      "test",
    48  						},
    49  					},
    50  				},
    51  			},
    52  		},
    53  	}
    54  
    55  	for _, test := range tests {
    56  		t.Run(test.input, func(t *testing.T) {
    57  			for i := range test.expected {
    58  				test.expected[i].Locations.Add(file.NewLocation(test.input))
    59  			}
    60  			pkgtest.TestFileParser(t, test.input, parserPomXML, test.expected, nil)
    61  		})
    62  	}
    63  }
    64  
    65  func Test_parseCommonsTextPomXMLProject(t *testing.T) {
    66  	tests := []struct {
    67  		input    string
    68  		expected []pkg.Package
    69  	}{
    70  		{
    71  			input: "test-fixtures/pom/commons-text.pom.xml",
    72  			expected: []pkg.Package{
    73  				{
    74  					Name:         "commons-lang3",
    75  					Version:      "3.12.0",
    76  					PURL:         "pkg:maven/org.apache.commons/commons-lang3@3.12.0",
    77  					Language:     pkg.Java,
    78  					Type:         pkg.JavaPkg,
    79  					MetadataType: pkg.JavaMetadataType,
    80  					Metadata: pkg.JavaMetadata{
    81  						PomProperties: &pkg.PomProperties{
    82  							GroupID:    "org.apache.commons",
    83  							ArtifactID: "commons-lang3",
    84  						},
    85  					},
    86  				},
    87  				{
    88  					Name:         "junit-jupiter",
    89  					Version:      "",
    90  					PURL:         "pkg:maven/org.junit.jupiter/junit-jupiter",
    91  					Language:     pkg.Java,
    92  					Type:         pkg.JavaPkg,
    93  					MetadataType: pkg.JavaMetadataType,
    94  					Metadata: pkg.JavaMetadata{
    95  						PomProperties: &pkg.PomProperties{
    96  							GroupID:    "org.junit.jupiter",
    97  							ArtifactID: "junit-jupiter",
    98  							Scope:      "test",
    99  						},
   100  					},
   101  				},
   102  				{
   103  					Name:         "assertj-core",
   104  					Version:      "3.23.1",
   105  					PURL:         "pkg:maven/org.assertj/assertj-core@3.23.1",
   106  					Language:     pkg.Java,
   107  					Type:         pkg.JavaPkg,
   108  					MetadataType: pkg.JavaMetadataType,
   109  					Metadata: pkg.JavaMetadata{
   110  						PomProperties: &pkg.PomProperties{
   111  							GroupID:    "org.assertj",
   112  							ArtifactID: "assertj-core",
   113  							Scope:      "test",
   114  						},
   115  					},
   116  				},
   117  				{
   118  					Name:         "commons-io",
   119  					Version:      "2.11.0",
   120  					PURL:         "pkg:maven/commons-io/commons-io@2.11.0",
   121  					Language:     pkg.Java,
   122  					Type:         pkg.JavaPkg,
   123  					MetadataType: pkg.JavaMetadataType,
   124  					Metadata: pkg.JavaMetadata{
   125  						PomProperties: &pkg.PomProperties{
   126  							GroupID:    "commons-io",
   127  							ArtifactID: "commons-io",
   128  							Scope:      "test",
   129  						},
   130  					},
   131  				},
   132  				{
   133  					Name:         "mockito-inline",
   134  					Version:      "4.8.0",
   135  					PURL:         "pkg:maven/org.mockito/mockito-inline@4.8.0",
   136  					Language:     pkg.Java,
   137  					Type:         pkg.JavaPkg,
   138  					MetadataType: pkg.JavaMetadataType,
   139  					Metadata: pkg.JavaMetadata{
   140  						PomProperties: &pkg.PomProperties{
   141  							GroupID:    "org.mockito",
   142  							ArtifactID: "mockito-inline",
   143  							Scope:      "test",
   144  						},
   145  					},
   146  				},
   147  				{
   148  					Name:         "js",
   149  					Version:      "22.0.0.2",
   150  					PURL:         "pkg:maven/org.graalvm.js/js@22.0.0.2",
   151  					Language:     pkg.Java,
   152  					Type:         pkg.JavaPkg,
   153  					MetadataType: pkg.JavaMetadataType,
   154  					Metadata: pkg.JavaMetadata{
   155  						PomProperties: &pkg.PomProperties{
   156  							GroupID:    "org.graalvm.js",
   157  							ArtifactID: "js",
   158  							Scope:      "test",
   159  						},
   160  					},
   161  				},
   162  				{
   163  					Name:         "js-scriptengine",
   164  					Version:      "22.0.0.2",
   165  					PURL:         "pkg:maven/org.graalvm.js/js-scriptengine@22.0.0.2",
   166  					Language:     pkg.Java,
   167  					Type:         pkg.JavaPkg,
   168  					MetadataType: pkg.JavaMetadataType,
   169  					Metadata: pkg.JavaMetadata{
   170  						PomProperties: &pkg.PomProperties{
   171  							GroupID:    "org.graalvm.js",
   172  							ArtifactID: "js-scriptengine",
   173  							Scope:      "test",
   174  						},
   175  					},
   176  				},
   177  				{
   178  					Name:         "commons-rng-simple",
   179  					Version:      "1.4",
   180  					PURL:         "pkg:maven/org.apache.commons/commons-rng-simple@1.4",
   181  					Language:     pkg.Java,
   182  					Type:         pkg.JavaPkg,
   183  					MetadataType: pkg.JavaMetadataType,
   184  					Metadata: pkg.JavaMetadata{
   185  						PomProperties: &pkg.PomProperties{
   186  							GroupID:    "org.apache.commons",
   187  							ArtifactID: "commons-rng-simple",
   188  							Scope:      "test",
   189  						},
   190  					},
   191  				},
   192  				{
   193  					Name:         "jmh-core",
   194  					Version:      "1.35",
   195  					PURL:         "pkg:maven/org.openjdk.jmh/jmh-core@1.35",
   196  					Language:     pkg.Java,
   197  					Type:         pkg.JavaPkg,
   198  					MetadataType: pkg.JavaMetadataType,
   199  					Metadata: pkg.JavaMetadata{
   200  						PomProperties: &pkg.PomProperties{
   201  							GroupID:    "org.openjdk.jmh",
   202  							ArtifactID: "jmh-core",
   203  							Scope:      "test",
   204  						},
   205  					},
   206  				},
   207  				{
   208  					Name:         "jmh-generator-annprocess",
   209  					Version:      "1.35",
   210  					PURL:         "pkg:maven/org.openjdk.jmh/jmh-generator-annprocess@1.35",
   211  					Language:     pkg.Java,
   212  					Type:         pkg.JavaPkg,
   213  					MetadataType: pkg.JavaMetadataType,
   214  					Metadata: pkg.JavaMetadata{
   215  						PomProperties: &pkg.PomProperties{
   216  							GroupID:    "org.openjdk.jmh",
   217  							ArtifactID: "jmh-generator-annprocess",
   218  							Scope:      "test",
   219  						},
   220  					},
   221  				},
   222  			},
   223  		},
   224  	}
   225  
   226  	for _, test := range tests {
   227  		t.Run(test.input, func(t *testing.T) {
   228  			for i := range test.expected {
   229  				test.expected[i].Locations.Add(file.NewLocation(test.input))
   230  			}
   231  			pkgtest.TestFileParser(t, test.input, parserPomXML, test.expected, nil)
   232  		})
   233  	}
   234  }
   235  
   236  func Test_parsePomXMLProject(t *testing.T) {
   237  	tests := []struct {
   238  		expected pkg.PomProject
   239  	}{
   240  		{
   241  			expected: pkg.PomProject{
   242  				Path: "test-fixtures/pom/commons-codec.pom.xml",
   243  				Parent: &pkg.PomParent{
   244  					GroupID:    "org.apache.commons",
   245  					ArtifactID: "commons-parent",
   246  					Version:    "42",
   247  				},
   248  				GroupID:     "commons-codec",
   249  				ArtifactID:  "commons-codec",
   250  				Version:     "1.11",
   251  				Name:        "Apache Commons Codec",
   252  				Description: "The Apache Commons Codec package contains simple encoder and decoders for various formats such as Base64 and Hexadecimal.  In addition to these widely used encoders and decoders, the codec package also maintains a collection of phonetic encoding utilities.",
   253  				URL:         "http://commons.apache.org/proper/commons-codec/",
   254  			},
   255  		},
   256  	}
   257  
   258  	for _, test := range tests {
   259  		t.Run(test.expected.Path, func(t *testing.T) {
   260  			fixture, err := os.Open(test.expected.Path)
   261  			assert.NoError(t, err)
   262  
   263  			actual, err := parsePomXMLProject(fixture.Name(), fixture)
   264  			assert.NoError(t, err)
   265  
   266  			assert.Equal(t, &test.expected, actual)
   267  		})
   268  	}
   269  }
   270  
   271  func Test_pomParent(t *testing.T) {
   272  	tests := []struct {
   273  		name     string
   274  		input    gopom.Parent
   275  		expected *pkg.PomParent
   276  	}{
   277  		{
   278  			name: "only group ID",
   279  			input: gopom.Parent{
   280  				GroupID: "org.something",
   281  			},
   282  			expected: &pkg.PomParent{
   283  				GroupID: "org.something",
   284  			},
   285  		},
   286  		{
   287  			name: "only artifact ID",
   288  			input: gopom.Parent{
   289  				ArtifactID: "something",
   290  			},
   291  			expected: &pkg.PomParent{
   292  				ArtifactID: "something",
   293  			},
   294  		},
   295  		{
   296  			name: "only Version",
   297  			input: gopom.Parent{
   298  				Version: "something",
   299  			},
   300  			expected: &pkg.PomParent{
   301  				Version: "something",
   302  			},
   303  		},
   304  		{
   305  			name:     "empty",
   306  			input:    gopom.Parent{},
   307  			expected: nil,
   308  		},
   309  		{
   310  			name: "unused field",
   311  			input: gopom.Parent{
   312  				RelativePath: "something",
   313  			},
   314  			expected: nil,
   315  		},
   316  	}
   317  
   318  	for _, test := range tests {
   319  		t.Run(test.name, func(t *testing.T) {
   320  			assert.Equal(t, test.expected, pomParent(gopom.Project{}, test.input))
   321  		})
   322  	}
   323  }
   324  
   325  func Test_cleanDescription(t *testing.T) {
   326  	tests := []struct {
   327  		name     string
   328  		input    string
   329  		expected string
   330  	}{
   331  		{
   332  			name: "indent + multiline",
   333  			input: `        The Apache Commons Codec package contains simple encoder and decoders for
   334          various formats such as Base64 and Hexadecimal.  In addition to these
   335          widely used encoders and decoders, the codec package also maintains a
   336          collection of phonetic encoding utilities.`,
   337  			expected: "The Apache Commons Codec package contains simple encoder and decoders for various formats such as Base64 and Hexadecimal.  In addition to these widely used encoders and decoders, the codec package also maintains a collection of phonetic encoding utilities.",
   338  		},
   339  	}
   340  
   341  	for _, test := range tests {
   342  		t.Run(test.name, func(t *testing.T) {
   343  			assert.Equal(t, test.expected, cleanDescription(test.input))
   344  		})
   345  	}
   346  }
   347  
   348  func Test_resolveProperty(t *testing.T) {
   349  	tests := []struct {
   350  		name     string
   351  		property string
   352  		pom      gopom.Project
   353  		expected string
   354  	}{
   355  		{
   356  			name:     "property",
   357  			property: "${version.number}",
   358  			pom: gopom.Project{
   359  				Properties: gopom.Properties{
   360  					Entries: map[string]string{
   361  						"version.number": "12.5.0",
   362  					},
   363  				},
   364  			},
   365  			expected: "12.5.0",
   366  		},
   367  		{
   368  			name:     "groupId",
   369  			property: "${project.groupId}",
   370  			pom: gopom.Project{
   371  				GroupID: "org.some.group",
   372  			},
   373  			expected: "org.some.group",
   374  		},
   375  		{
   376  			name:     "parent groupId",
   377  			property: "${project.parent.groupId}",
   378  			pom: gopom.Project{
   379  				Parent: gopom.Parent{
   380  					GroupID: "org.some.parent",
   381  				},
   382  			},
   383  			expected: "org.some.parent",
   384  		},
   385  	}
   386  
   387  	for _, test := range tests {
   388  		t.Run(test.name, func(t *testing.T) {
   389  			resolved := resolveProperty(test.pom, test.property)
   390  			assert.Equal(t, test.expected, resolved)
   391  		})
   392  	}
   393  }