github.com/vmware/govmomi@v0.43.0/ovf/parser_test.go (about)

     1  /*
     2  Copyright (c) 2019-2024 VMware, Inc. All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package ovf
    18  
    19  import (
    20  	"fmt"
    21  	"strings"
    22  	"testing"
    23  
    24  	"github.com/stretchr/testify/assert"
    25  )
    26  
    27  func TestValidInteger(t *testing.T) {
    28  	t.Run("Valid integer terms", func(t *testing.T) {
    29  		testCases := []string{
    30  			"1",
    31  			"1024",
    32  			"1000",
    33  			"1000000000",
    34  		}
    35  
    36  		for _, tc := range testCases {
    37  			t.Run(tc, func(t *testing.T) {
    38  				assert.True(t, validIntegerString(tc))
    39  			})
    40  		}
    41  	})
    42  
    43  	// while these all may not necessarily be invalid integer terms mathematically, they are either not valid per
    44  	// DSP0004, or not valid per our use-case
    45  	t.Run("Invalid integer terms", func(t *testing.T) {
    46  		testCases := []string{
    47  			"05",
    48  			"1.5",
    49  			"2^10",
    50  			"-10",
    51  			"1,000",
    52  			"1,000,000",
    53  		}
    54  
    55  		for _, tc := range testCases {
    56  			t.Run(tc, func(t *testing.T) {
    57  				assert.False(t, validIntegerString(tc))
    58  			})
    59  		}
    60  	})
    61  }
    62  
    63  func TestValidExponent(t *testing.T) {
    64  	t.Run("Acceptable exponential terms", func(t *testing.T) {
    65  		testCases := []string{
    66  			"10^3",
    67  			"2^10",
    68  		}
    69  
    70  		for _, tc := range testCases {
    71  			t.Run(tc, func(t *testing.T) {
    72  				assert.True(t, validExponentString(tc))
    73  			})
    74  		}
    75  	})
    76  
    77  	// while valid exponential terms mathematically, they are either not valid per DSP0004, or not valid per our
    78  	// use-case
    79  	t.Run("Unacceptable exponential terms", func(t *testing.T) {
    80  		testCases := []string{
    81  			"1",
    82  			"1024",
    83  			"05",
    84  			"1.5",
    85  			"-10",
    86  			"0.5^2",
    87  			"-10^3",
    88  			"-2^10",
    89  			"1e6",
    90  		}
    91  
    92  		for _, tc := range testCases {
    93  			t.Run(tc, func(t *testing.T) {
    94  				assert.False(t, validExponentString(tc))
    95  			})
    96  		}
    97  	})
    98  }
    99  
   100  func TestValidByteUnitString(t *testing.T) {
   101  	// Due to size constraints and our use-case, we only accept up to gigabyte
   102  	t.Run("Acceptable SI decimal prefixes", func(t *testing.T) {
   103  		testCases := []string{
   104  			"byte",
   105  			"kilobyte",
   106  			"megabyte",
   107  			"gigabyte",
   108  		}
   109  
   110  		for _, tc := range testCases {
   111  			t.Run(tc, func(t *testing.T) {
   112  				assert.True(t, validByteUnitString(tc))
   113  			})
   114  			// plural is valid
   115  			plural := fmt.Sprintf("%ss", tc)
   116  			t.Run(plural, func(t *testing.T) {
   117  				assert.True(t, validByteUnitString(plural))
   118  			})
   119  			// function expects an already lowercased string, so capitalization is not valid
   120  			capitalized := strings.ToUpper(tc)
   121  			t.Run(capitalized, func(t *testing.T) {
   122  				assert.False(t, validByteUnitString(capitalized))
   123  			})
   124  		}
   125  	})
   126  
   127  	// too large and/or currently don't fit use-case
   128  	t.Run("Unacceptable SI decimal prefixes", func(t *testing.T) {
   129  		testCases := []string{
   130  			"terabyte",
   131  			"petabyte",
   132  			"exabyte",
   133  			"zettabyte",
   134  			"yottabyte",
   135  		}
   136  
   137  		for _, tc := range testCases {
   138  			t.Run(tc, func(t *testing.T) {
   139  				assert.False(t, validByteUnitString(tc))
   140  			})
   141  		}
   142  	})
   143  
   144  	// due to size constraints and our use-case, we only accept up to gibibyte
   145  	t.Run("Acceptable IEC binary prefixes", func(t *testing.T) {
   146  		testCases := []string{
   147  			"kibibyte",
   148  			"mebibyte",
   149  			"gibibyte",
   150  		}
   151  
   152  		for _, tc := range testCases {
   153  			t.Run(tc, func(t *testing.T) {
   154  				assert.True(t, validByteUnitString(tc))
   155  			})
   156  			// plural is valid
   157  			plural := fmt.Sprintf("%ss", tc)
   158  			t.Run(plural, func(t *testing.T) {
   159  				assert.True(t, validByteUnitString(plural))
   160  			})
   161  			// function expects an already-lowercased string, so capitalization is not valid
   162  			capitalized := strings.ToUpper(tc)
   163  			t.Run(capitalized, func(t *testing.T) {
   164  				assert.False(t, validByteUnitString(capitalized))
   165  			})
   166  		}
   167  	})
   168  
   169  	// too large and/or currently don't fit use-case
   170  	t.Run("Unacceptable IEC binary prefixes", func(t *testing.T) {
   171  		testCases := []string{
   172  			"tebibyte",
   173  			"pebibyte",
   174  			"exbibyte",
   175  			"zebibyte",
   176  			"yobibyte",
   177  		}
   178  
   179  		for _, tc := range testCases {
   180  			t.Run(tc, func(t *testing.T) {
   181  				assert.False(t, validByteUnitString(tc))
   182  			})
   183  		}
   184  	})
   185  }
   186  
   187  func TestValidUnit(t *testing.T) {
   188  	t.Run("Valid unit strings", func(t *testing.T) {
   189  		testCases := []string{
   190  			"",
   191  			"1024",
   192  			"2^10",
   193  			"10^3",
   194  			"byte",
   195  			"1024*byte",
   196  			"1024 * byte",
   197  			"byte*1024",
   198  			"byte * 1024",
   199  			"2^10*byte",
   200  			"2^10 * bytes",
   201  			"byte*2^10",
   202  			"byte * 2^10",
   203  			"1024 * 1024*1024",
   204  			"2^10*2^10 * 2^10",
   205  			"2^10 * 1024 * 2^10",
   206  			"2^10*1024 * byte",
   207  			"byte*2^10 * 1024",
   208  			"1000*byte * 1000 * 1000",
   209  			"gigabyte",
   210  			"Gigabyte",
   211  			"1024 * 1024 * kilobyte",
   212  			"Byte",
   213  			"1024*Byte",
   214  			"1024 * BYTE",
   215  			"BYTE*1024",
   216  			"Byte * 1024",
   217  			"2^10*Byte",
   218  			"2^10 * BYTE",
   219  			"BYTE*2^10",
   220  			"Byte * 2^10",
   221  			"1000000",
   222  			"1000000000*byte",
   223  		}
   224  
   225  		for _, tc := range testCases {
   226  			t.Run(tc, func(t *testing.T) {
   227  				assert.True(t, validCapacityString(tc))
   228  			})
   229  		}
   230  	})
   231  
   232  	// either these do not abide by DSP0004, or they do not make sense in the context of our use-case
   233  	t.Run("Invalid unit strings", func(t *testing.T) {
   234  		testCases := []string{
   235  			"1000*",
   236  			"*1024",
   237  			"* 1000 * byte",
   238  			"byte * 2^30 *",
   239  			"1000byte",
   240  			"1024*1024*",
   241  			"byte*byte",
   242  			"2^10/1024",
   243  			"1024*1024 / 1024",
   244  			"2 ^ 10",
   245  			"512 + 512",
   246  			"2048 - 1024",
   247  			"1,000,000",
   248  			"1,000,000,000*byte",
   249  		}
   250  
   251  		for _, tc := range testCases {
   252  			t.Run(tc, func(t *testing.T) {
   253  				assert.False(t, validCapacityString(tc))
   254  			})
   255  		}
   256  	})
   257  }
   258  
   259  func TestParseCapacityAllocationUnits(t *testing.T) {
   260  	t.Run("Valid capacity allocation units multiplier is correctly parsed", func(t *testing.T) {
   261  		testCases := []struct {
   262  			s        string
   263  			expected int64
   264  		}{
   265  			{"", 1},
   266  			{"byte", 1},
   267  			{"kilobyte", 1000},
   268  			{"kibibyte", 1024},
   269  			{"megabyte", 1000 * 1000},
   270  			{"mebibyte", 1024 * 1024},
   271  			{"gigabyte", 1000 * 1000 * 1000},
   272  			{"gibibyte", 1024 * 1024 * 1024},
   273  			{"Byte", 1},
   274  			{"Kilobyte", 1000},
   275  			{"Kibibyte", 1024},
   276  			{"Megabyte", 1000 * 1000},
   277  			{"Mebibyte", 1024 * 1024},
   278  			{"Gigabyte", 1000 * 1000 * 1000},
   279  			{"Gibibyte", 1024 * 1024 * 1024},
   280  			{"BYTE", 1},
   281  			{"KILOBYTE", 1000},
   282  			{"KIBIBYTE", 1024},
   283  			{"MEGABYTE", 1000 * 1000},
   284  			{"MEBIBYTE", 1024 * 1024},
   285  			{"GIGABYTE", 1000 * 1000 * 1000},
   286  			{"GIBIBYTE", 1024 * 1024 * 1024},
   287  			{"10^3", 1000},
   288  			{"1024", 1024},
   289  			{"1000 * byte", 1000},
   290  			{"2^10 * byte", 1024},
   291  			{"byte * 2^10", 1024},
   292  			{"10^9*byte", 1000 * 1000 * 1000},
   293  			{"10^3 * megabyte", 1000 * 1000 * 1000},
   294  			{"kibibyte * 2^10 * 1024", 1024 * 1024 * 1024},
   295  			{"byte*2^10*2^10*1024", 1024 * 1024 * 1024},
   296  			{"1000*byte*1000*10^3", 1000 * 1000 * 1000},
   297  		}
   298  
   299  		for _, tc := range testCases {
   300  			t.Run(tc.s, func(t *testing.T) {
   301  				assert.Equal(t, tc.expected, ParseCapacityAllocationUnits(tc.s))
   302  			})
   303  		}
   304  	})
   305  
   306  	// either these do not abide by DSP0004, or they do not make sense in the context of our use-case
   307  	t.Run("Invalid capacity allocation units should return zero", func(t *testing.T) {
   308  		testCases := []string{
   309  			"bit", // the only unit, valid per DSP0004, that we care about is byte; this makes more sense than checking meter
   310  			"nibble",
   311  			"dataword",
   312  			"byte*byte",
   313  			"1000*",
   314  			"*1024",
   315  			"* 1000 * byte",
   316  			"byte * 2^30 *",
   317  			"1000byte",
   318  			"1024*1024*",
   319  			"byte*byte",
   320  			"2^10/1024",
   321  			"1024*1024 / 1024",
   322  			"2 ^ 10",
   323  			"512 + 512",
   324  			"2048 - 1024",
   325  		}
   326  
   327  		for _, tc := range testCases {
   328  			t.Run(tc, func(t *testing.T) {
   329  				assert.Equal(t, int64(0), ParseCapacityAllocationUnits(tc))
   330  			})
   331  		}
   332  	})
   333  }