github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/finder/fs/readdir_test.go (about)

     1  // Copyright 2017 Google Inc. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package fs
    16  
    17  import (
    18  	"os"
    19  	"reflect"
    20  	"runtime"
    21  	"testing"
    22  )
    23  
    24  func TestParseDirent(t *testing.T) {
    25  	testCases := []struct {
    26  		name string
    27  		in   []byte
    28  		out  []*dirEntryInfo
    29  	}{
    30  		{
    31  			// Test that type DT_DIR is translated to os.ModeDir
    32  			name: "dir",
    33  			in: []byte{
    34  				// __ino64_t d_ino;
    35  				0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
    36  				// __off64_t d_off;
    37  				0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
    38  				// unsigned short int d_reclen;
    39  				0x28, 0x00,
    40  				// unsigned char d_type;
    41  				0x04,
    42  				// char d_name[];
    43  				0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73,
    44  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    45  			},
    46  			out: []*dirEntryInfo{
    47  				{".module_paths", os.ModeDir, true},
    48  			},
    49  		},
    50  		{
    51  			// Test that type DT_REG is translated to a regular file
    52  			name: "file",
    53  			in: []byte{
    54  				// __ino64_t d_ino;
    55  				0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
    56  				// __off64_t d_off;
    57  				0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
    58  				// unsigned short int d_reclen;
    59  				0x28, 0x00,
    60  				// unsigned char d_type;
    61  				0x08,
    62  				// char d_name[];
    63  				0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73,
    64  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    65  			},
    66  			out: []*dirEntryInfo{
    67  				{".module_paths", 0, true},
    68  			},
    69  		},
    70  		{
    71  			// Test that type DT_LNK is translated to a regular os.ModeSymlink
    72  			name: "symlink",
    73  			in: []byte{
    74  				// __ino64_t d_ino;
    75  				0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
    76  				// __off64_t d_off;
    77  				0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
    78  				// unsigned short int d_reclen;
    79  				0x28, 0x00,
    80  				// unsigned char d_type;
    81  				0x0a,
    82  				// char d_name[];
    83  				0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73,
    84  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    85  			},
    86  			out: []*dirEntryInfo{
    87  				{".module_paths", os.ModeSymlink, true},
    88  			},
    89  		},
    90  		{
    91  			// Test that type DT_UNKNOWN sets modeExists: false
    92  			name: "unknown",
    93  			in: []byte{
    94  				// __ino64_t d_ino;
    95  				0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
    96  				// __off64_t d_off;
    97  				0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
    98  				// unsigned short int d_reclen;
    99  				0x28, 0x00,
   100  				// unsigned char d_type;
   101  				0x00,
   102  				// char d_name[];
   103  				0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73,
   104  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   105  			},
   106  			out: []*dirEntryInfo{
   107  				{".module_paths", 0, false},
   108  			},
   109  		},
   110  		{
   111  			// Test a name with no padding after the null terminator
   112  			name: "no padding",
   113  			in: []byte{
   114  				// __ino64_t d_ino;
   115  				0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
   116  				// __off64_t d_off;
   117  				0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
   118  				// unsigned short int d_reclen;
   119  				0x20, 0x00,
   120  				// unsigned char d_type;
   121  				0x04,
   122  				// char d_name[];
   123  				0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x00,
   124  			},
   125  			out: []*dirEntryInfo{
   126  				{".module_path", os.ModeDir, true},
   127  			},
   128  		},
   129  		{
   130  			// Test two sequential entries
   131  			name: "two entries",
   132  			in: []byte{
   133  				// __ino64_t d_ino;
   134  				0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
   135  				// __off64_t d_off;
   136  				0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
   137  				// unsigned short int d_reclen;
   138  				0x28, 0x00,
   139  				// unsigned char d_type;
   140  				0x04,
   141  				// char d_name[];
   142  				0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73,
   143  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   144  
   145  				// __ino64_t d_ino;
   146  				0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
   147  				// __off64_t d_off;
   148  				0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
   149  				// unsigned short int d_reclen;
   150  				0x28, 0x00,
   151  				// unsigned char d_type;
   152  				0x04,
   153  				// char d_name[];
   154  				0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x74,
   155  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   156  			},
   157  			out: []*dirEntryInfo{
   158  				{".module_paths", os.ModeDir, true},
   159  				{".module_patht", os.ModeDir, true},
   160  			},
   161  		},
   162  		{
   163  			// Test two sequential entries with no padding between them
   164  			name: "two entries no padding",
   165  			in: []byte{
   166  				// __ino64_t d_ino;
   167  				0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
   168  				// __off64_t d_off;
   169  				0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
   170  				// unsigned short int d_reclen;
   171  				0x20, 0x00,
   172  				// unsigned char d_type;
   173  				0x04,
   174  				// char d_name[];
   175  				0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x00,
   176  
   177  				// __ino64_t d_ino;
   178  				0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
   179  				// __off64_t d_off;
   180  				0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
   181  				// unsigned short int d_reclen;
   182  				0x28, 0x00,
   183  				// unsigned char d_type;
   184  				0x04,
   185  				// char d_name[];
   186  				0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73,
   187  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   188  			},
   189  			out: []*dirEntryInfo{
   190  				{".module_path", os.ModeDir, true},
   191  				{".module_paths", os.ModeDir, true},
   192  			},
   193  		},
   194  		{
   195  			// Test an empty buffer.  This shouldn't happen in practice because
   196  			// readdir doesn't call parseDirent if no bytes were returned.
   197  			name: "empty",
   198  			in:   []byte{},
   199  			out:  nil,
   200  		},
   201  		{
   202  			name: "missing null terminator",
   203  			in: []byte{
   204  				// __ino64_t d_ino;
   205  				0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
   206  				// __off64_t d_off;
   207  				0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
   208  				// unsigned short int d_reclen;
   209  				0x20, 0x00,
   210  				// unsigned char d_type;
   211  				0x04,
   212  				// char d_name[];
   213  				0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73,
   214  			},
   215  			out: []*dirEntryInfo{
   216  				{".module_paths", os.ModeDir, true},
   217  			},
   218  		},
   219  		{
   220  			// Test two sequential entries where the first has an incorrect d_reclen.
   221  			// Should return with no entries.
   222  			name: "two entries first malformed",
   223  			in: []byte{
   224  				// __ino64_t d_ino;
   225  				0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
   226  				// __off64_t d_off;
   227  				0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
   228  				// unsigned short int d_reclen;
   229  				0x10, 0x00,
   230  				// unsigned char d_type;
   231  				0x04,
   232  				// char d_name[];
   233  				0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x00,
   234  
   235  				// __ino64_t d_ino;
   236  				0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
   237  				// __off64_t d_off;
   238  				0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
   239  				// unsigned short int d_reclen;
   240  				0x28, 0x00,
   241  				// unsigned char d_type;
   242  				0x04,
   243  				// char d_name[];
   244  				0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73,
   245  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   246  			},
   247  			out: nil,
   248  		},
   249  		{
   250  			// Test two sequential entries where the second has an incorrect d_reclen.
   251  			// Should return the first entry.
   252  			name: "two entries second malformed",
   253  			in: []byte{
   254  				// __ino64_t d_ino;
   255  				0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
   256  				// __off64_t d_off;
   257  				0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
   258  				// unsigned short int d_reclen;
   259  				0x28, 0x00,
   260  				// unsigned char d_type;
   261  				0x04,
   262  				// char d_name[];
   263  				0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x00,
   264  
   265  				// __ino64_t d_ino;
   266  				0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
   267  				// __off64_t d_off;
   268  				0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
   269  				// unsigned short int d_reclen;
   270  				0x10, 0x00,
   271  				// unsigned char d_type;
   272  				0x04,
   273  				// char d_name[];
   274  				0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73,
   275  				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   276  			},
   277  			out: []*dirEntryInfo{
   278  				{".module_path", os.ModeDir, true},
   279  			},
   280  		},
   281  		{
   282  			// Test a reclen that goes past the end of the buffer.
   283  			name: "overrun",
   284  			in: []byte{
   285  				// __ino64_t d_ino;
   286  				0xfb, 0x10, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00,
   287  				// __off64_t d_off;
   288  				0xeb, 0x85, 0x20, 0x91, 0xb9, 0x14, 0x34, 0x03,
   289  				// unsigned short int d_reclen;
   290  				0x30, 0x00,
   291  				// unsigned char d_type;
   292  				0x04,
   293  				// char d_name[];
   294  				0x2e, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x00,
   295  			},
   296  			out: nil,
   297  		},
   298  	}
   299  
   300  	if runtime.GOOS != "linux" {
   301  		t.Skip("depends on Linux definitions of syscall.Dirent")
   302  	}
   303  
   304  	for _, testCase := range testCases {
   305  		t.Run(testCase.name, func(t *testing.T) {
   306  			entries := parseDirent(testCase.in, nil)
   307  			if !reflect.DeepEqual(testCase.out, entries) {
   308  				t.Fatalf("expected:\n %v\ngot:\n %v\n", testCase.out, entries)
   309  			}
   310  		})
   311  	}
   312  }