...

Source file src/github.com/go-ldap/ldap/v3/filter_test.go

Documentation: github.com/go-ldap/ldap/v3

     1  package ldap
     2  
     3  import (
     4  	"strings"
     5  	"testing"
     6  
     7  	ber "github.com/go-asn1-ber/asn1-ber"
     8  )
     9  
    10  type compileTest struct {
    11  	filterStr string
    12  
    13  	expectedFilter string
    14  	expectedType   int
    15  	expectedErr    string
    16  }
    17  
    18  var testFilters = []compileTest{
    19  	{
    20  		filterStr:      "(&(sn=Miller)(givenName=Bob))",
    21  		expectedFilter: "(&(sn=Miller)(givenName=Bob))",
    22  		expectedType:   FilterAnd,
    23  	},
    24  	{
    25  		filterStr:      "(|(sn=Miller)(givenName=Bob))",
    26  		expectedFilter: "(|(sn=Miller)(givenName=Bob))",
    27  		expectedType:   FilterOr,
    28  	},
    29  	{
    30  		filterStr:      "(!(sn=Miller))",
    31  		expectedFilter: "(!(sn=Miller))",
    32  		expectedType:   FilterNot,
    33  	},
    34  	{
    35  		filterStr:      "(sn=Miller)",
    36  		expectedFilter: "(sn=Miller)",
    37  		expectedType:   FilterEqualityMatch,
    38  	},
    39  	{
    40  		filterStr:      "(sn=Mill*)",
    41  		expectedFilter: "(sn=Mill*)",
    42  		expectedType:   FilterSubstrings,
    43  	},
    44  	{
    45  		filterStr:      "(sn=*Mill)",
    46  		expectedFilter: "(sn=*Mill)",
    47  		expectedType:   FilterSubstrings,
    48  	},
    49  	{
    50  		filterStr:      "(sn=*Mill*)",
    51  		expectedFilter: "(sn=*Mill*)",
    52  		expectedType:   FilterSubstrings,
    53  	},
    54  	{
    55  		filterStr:      "(sn=*i*le*)",
    56  		expectedFilter: "(sn=*i*le*)",
    57  		expectedType:   FilterSubstrings,
    58  	},
    59  	{
    60  		filterStr:      "(sn=Mi*l*r)",
    61  		expectedFilter: "(sn=Mi*l*r)",
    62  		expectedType:   FilterSubstrings,
    63  	},
    64  	// substring filters escape properly
    65  	{
    66  		filterStr:      `(sn=Mi*함*r)`,
    67  		expectedFilter: `(sn=Mi*\ed\95\a8*r)`,
    68  		expectedType:   FilterSubstrings,
    69  	},
    70  	// already escaped substring filters don't get double-escaped
    71  	{
    72  		filterStr:      `(sn=Mi*\ed\95\a8*r)`,
    73  		expectedFilter: `(sn=Mi*\ed\95\a8*r)`,
    74  		expectedType:   FilterSubstrings,
    75  	},
    76  	{
    77  		filterStr:      "(sn=Mi*le*)",
    78  		expectedFilter: "(sn=Mi*le*)",
    79  		expectedType:   FilterSubstrings,
    80  	},
    81  	{
    82  		filterStr:      "(sn=*i*ler)",
    83  		expectedFilter: "(sn=*i*ler)",
    84  		expectedType:   FilterSubstrings,
    85  	},
    86  	{
    87  		filterStr:      "(sn>=Miller)",
    88  		expectedFilter: "(sn>=Miller)",
    89  		expectedType:   FilterGreaterOrEqual,
    90  	},
    91  	{
    92  		filterStr:      "(sn<=Miller)",
    93  		expectedFilter: "(sn<=Miller)",
    94  		expectedType:   FilterLessOrEqual,
    95  	},
    96  	{
    97  		filterStr:      "(sn=*)",
    98  		expectedFilter: "(sn=*)",
    99  		expectedType:   FilterPresent,
   100  	},
   101  	{
   102  		filterStr:      "(sn~=Miller)",
   103  		expectedFilter: "(sn~=Miller)",
   104  		expectedType:   FilterApproxMatch,
   105  	},
   106  	{
   107  		filterStr:      `(objectGUID='\fc\fe\a3\ab\f9\90N\aaGm\d5I~\d12)`,
   108  		expectedFilter: `(objectGUID='\fc\fe\a3\ab\f9\90N\aaGm\d5I~\d12)`,
   109  		expectedType:   FilterEqualityMatch,
   110  	},
   111  	{
   112  		filterStr:      `(objectGUID=абвгдеёжзийклмнопрстуфхцчшщъыьэюя)`,
   113  		expectedFilter: `(objectGUID=\d0\b0\d0\b1\d0\b2\d0\b3\d0\b4\d0\b5\d1\91\d0\b6\d0\b7\d0\b8\d0\b9\d0\ba\d0\bb\d0\bc\d0\bd\d0\be\d0\bf\d1\80\d1\81\d1\82\d1\83\d1\84\d1\85\d1\86\d1\87\d1\88\d1\89\d1\8a\d1\8b\d1\8c\d1\8d\d1\8e\d1\8f)`,
   114  		expectedType:   FilterEqualityMatch,
   115  	},
   116  	{
   117  		filterStr:      `(objectGUID=함수목록)`,
   118  		expectedFilter: `(objectGUID=\ed\95\a8\ec\88\98\eb\aa\a9\eb\a1\9d)`,
   119  		expectedType:   FilterEqualityMatch,
   120  	},
   121  	{
   122  		filterStr:      `(objectGUID=`,
   123  		expectedFilter: ``,
   124  		expectedType:   0,
   125  		expectedErr:    "unexpected end of filter",
   126  	},
   127  	{
   128  		filterStr:      `(objectGUID=함수목록`,
   129  		expectedFilter: ``,
   130  		expectedType:   0,
   131  		expectedErr:    "unexpected end of filter",
   132  	},
   133  	{
   134  		filterStr:      `((cn=)`,
   135  		expectedFilter: ``,
   136  		expectedType:   0,
   137  		expectedErr:    "unexpected end of filter",
   138  	},
   139  	{
   140  		filterStr:      `(&(objectclass=inetorgperson)(cn=中文))`,
   141  		expectedFilter: `(&(objectclass=inetorgperson)(cn=\e4\b8\ad\e6\96\87))`,
   142  		expectedType:   0,
   143  	},
   144  	// attr extension
   145  	{
   146  		filterStr:      `(memberOf:=foo)`,
   147  		expectedFilter: `(memberOf:=foo)`,
   148  		expectedType:   FilterExtensibleMatch,
   149  	},
   150  	// attr+named matching rule extension
   151  	{
   152  		filterStr:      `(memberOf:test:=foo)`,
   153  		expectedFilter: `(memberOf:test:=foo)`,
   154  		expectedType:   FilterExtensibleMatch,
   155  	},
   156  	// attr+oid matching rule extension
   157  	{
   158  		filterStr:      `(cn:1.2.3.4.5:=Fred Flintstone)`,
   159  		expectedFilter: `(cn:1.2.3.4.5:=Fred Flintstone)`,
   160  		expectedType:   FilterExtensibleMatch,
   161  	},
   162  	// attr+dn+oid matching rule extension
   163  	{
   164  		filterStr:      `(sn:dn:2.4.6.8.10:=Barney Rubble)`,
   165  		expectedFilter: `(sn:dn:2.4.6.8.10:=Barney Rubble)`,
   166  		expectedType:   FilterExtensibleMatch,
   167  	},
   168  	// attr+dn extension
   169  	{
   170  		filterStr:      `(o:dn:=Ace Industry)`,
   171  		expectedFilter: `(o:dn:=Ace Industry)`,
   172  		expectedType:   FilterExtensibleMatch,
   173  	},
   174  	// dn extension
   175  	{
   176  		filterStr:      `(:dn:2.4.6.8.10:=Dino)`,
   177  		expectedFilter: `(:dn:2.4.6.8.10:=Dino)`,
   178  		expectedType:   FilterExtensibleMatch,
   179  	},
   180  	{
   181  		filterStr:      `(memberOf:1.2.840.113556.1.4.1941:=CN=User1,OU=blah,DC=mydomain,DC=net)`,
   182  		expectedFilter: `(memberOf:1.2.840.113556.1.4.1941:=CN=User1,OU=blah,DC=mydomain,DC=net)`,
   183  		expectedType:   FilterExtensibleMatch,
   184  	},
   185  
   186  	// compileTest{ filterStr: "()", filterType: FilterExtensibleMatch },
   187  }
   188  
   189  var testInvalidFilters = []string{
   190  	`(objectGUID=\zz)`,
   191  	`(objectGUID=\a)`,
   192  }
   193  
   194  func TestFilter(t *testing.T) {
   195  	// Test Compiler and Decompiler
   196  	for _, i := range testFilters {
   197  		filter, err := CompileFilter(i.filterStr)
   198  		switch {
   199  		case err != nil:
   200  			if i.expectedErr == "" || !strings.Contains(err.Error(), i.expectedErr) {
   201  				t.Errorf("Problem compiling '%s' - '%v' (expected error to contain '%v')", i.filterStr, err, i.expectedErr)
   202  			}
   203  		case filter.Tag != ber.Tag(i.expectedType):
   204  			t.Errorf("%q Expected %q got %q", i.filterStr, FilterMap[uint64(i.expectedType)], FilterMap[uint64(filter.Tag)])
   205  		default:
   206  			o, err := DecompileFilter(filter)
   207  			if err != nil {
   208  				t.Errorf("Problem compiling %s - %s", i.filterStr, err.Error())
   209  			} else if i.expectedFilter != o {
   210  				t.Errorf("%q expected, got %q", i.expectedFilter, o)
   211  			}
   212  		}
   213  	}
   214  }
   215  
   216  func TestDecodeEscapedSymbols(t *testing.T) {
   217  	for _, testInfo := range []struct {
   218  		Src string
   219  		Err string
   220  	}{
   221  		{
   222  			Src: "a\u0100\x80",
   223  			Err: `LDAP Result Code 201 "Filter Compile Error": ldap: error reading rune at position 3`,
   224  		},
   225  		{
   226  			Src: `start\d`,
   227  			Err: `LDAP Result Code 201 "Filter Compile Error": ldap: missing characters for escape in filter`,
   228  		},
   229  		{
   230  			Src: `\`,
   231  			Err: `LDAP Result Code 201 "Filter Compile Error": ldap: invalid characters for escape in filter: EOF`,
   232  		},
   233  		{
   234  			Src: `start\--end`,
   235  			Err: `LDAP Result Code 201 "Filter Compile Error": ldap: invalid characters for escape in filter: encoding/hex: invalid byte: U+002D '-'`,
   236  		},
   237  		{
   238  			Src: `start\d0\hh`,
   239  			Err: `LDAP Result Code 201 "Filter Compile Error": ldap: invalid characters for escape in filter: encoding/hex: invalid byte: U+0068 'h'`,
   240  		},
   241  	} {
   242  
   243  		res, err := decodeEscapedSymbols([]byte(testInfo.Src))
   244  		if err == nil || err.Error() != testInfo.Err {
   245  			t.Fatal(testInfo.Src, "=> ", err, "!=", testInfo.Err)
   246  		}
   247  		if res != "" {
   248  			t.Fatal(testInfo.Src, "=> ", "invalid result", res)
   249  		}
   250  	}
   251  }
   252  
   253  func TestInvalidFilter(t *testing.T) {
   254  	for _, filterStr := range testInvalidFilters {
   255  		if _, err := CompileFilter(filterStr); err == nil {
   256  			t.Errorf("Problem compiling %s - expected err", filterStr)
   257  		}
   258  	}
   259  }
   260  
   261  func BenchmarkFilterCompile(b *testing.B) {
   262  	b.StopTimer()
   263  	filters := make([]string, len(testFilters))
   264  
   265  	// Test Compiler and Decompiler
   266  	for idx, i := range testFilters {
   267  		filters[idx] = i.filterStr
   268  	}
   269  
   270  	maxIdx := len(filters)
   271  	b.StartTimer()
   272  	for i := 0; i < b.N; i++ {
   273  		_, _ = CompileFilter(filters[i%maxIdx])
   274  	}
   275  }
   276  
   277  func BenchmarkFilterDecompile(b *testing.B) {
   278  	b.StopTimer()
   279  	filters := make([]*ber.Packet, len(testFilters))
   280  
   281  	// Test Compiler and Decompiler
   282  	for idx, i := range testFilters {
   283  		filters[idx], _ = CompileFilter(i.filterStr)
   284  	}
   285  
   286  	maxIdx := len(filters)
   287  	b.StartTimer()
   288  	for i := 0; i < b.N; i++ {
   289  		_, _ = DecompileFilter(filters[i%maxIdx])
   290  	}
   291  }
   292  

View as plain text