get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/internal/ldap/dn_test.go (about) 1 // Copyright (c) 2011-2015 Michael Mitton (mmitton@gmail.com) 2 // Portions copyright (c) 2015-2016 go-ldap Authors 3 package ldap 4 5 import ( 6 "reflect" 7 "testing" 8 ) 9 10 func TestSuccessfulDNParsing(t *testing.T) { 11 testcases := map[string]DN{ 12 "": {[]*RelativeDN{}}, 13 "cn=Jim\\2C \\22Hasse Hö\\22 Hansson!,dc=dummy,dc=com": {[]*RelativeDN{ 14 {[]*AttributeTypeAndValue{{"cn", "Jim, \"Hasse Hö\" Hansson!"}}}, 15 {[]*AttributeTypeAndValue{{"dc", "dummy"}}}, 16 {[]*AttributeTypeAndValue{{"dc", "com"}}}}}, 17 "UID=jsmith,DC=example,DC=net": {[]*RelativeDN{ 18 {[]*AttributeTypeAndValue{{"UID", "jsmith"}}}, 19 {[]*AttributeTypeAndValue{{"DC", "example"}}}, 20 {[]*AttributeTypeAndValue{{"DC", "net"}}}}}, 21 "OU=Sales+CN=J. Smith,DC=example,DC=net": {[]*RelativeDN{ 22 {[]*AttributeTypeAndValue{ 23 {"OU", "Sales"}, 24 {"CN", "J. Smith"}}}, 25 {[]*AttributeTypeAndValue{{"DC", "example"}}}, 26 {[]*AttributeTypeAndValue{{"DC", "net"}}}}}, 27 // 28 // "1.3.6.1.4.1.1466.0=#04024869": {[]*RelativeDN{ 29 // {[]*AttributeTypeAndValue{{"1.3.6.1.4.1.1466.0", "Hi"}}}}}, 30 // "1.3.6.1.4.1.1466.0=#04024869,DC=net": {[]*RelativeDN{ 31 // {[]*AttributeTypeAndValue{{"1.3.6.1.4.1.1466.0", "Hi"}}}, 32 // {[]*AttributeTypeAndValue{{"DC", "net"}}}}}, 33 "CN=Lu\\C4\\8Di\\C4\\87": {[]*RelativeDN{ 34 {[]*AttributeTypeAndValue{{"CN", "Lučić"}}}}}, 35 " CN = Lu\\C4\\8Di\\C4\\87 ": {[]*RelativeDN{ 36 {[]*AttributeTypeAndValue{{"CN", "Lučić"}}}}}, 37 ` A = 1 , B = 2 `: {[]*RelativeDN{ 38 {[]*AttributeTypeAndValue{{"A", "1"}}}, 39 {[]*AttributeTypeAndValue{{"B", "2"}}}}}, 40 ` A = 1 + B = 2 `: {[]*RelativeDN{ 41 {[]*AttributeTypeAndValue{ 42 {"A", "1"}, 43 {"B", "2"}}}}}, 44 ` \ \ A\ \ = \ \ 1\ \ , \ \ B\ \ = \ \ 2\ \ `: {[]*RelativeDN{ 45 {[]*AttributeTypeAndValue{{" A ", " 1 "}}}, 46 {[]*AttributeTypeAndValue{{" B ", " 2 "}}}}}, 47 ` \ \ A\ \ = \ \ 1\ \ + \ \ B\ \ = \ \ 2\ \ `: {[]*RelativeDN{ 48 {[]*AttributeTypeAndValue{ 49 {" A ", " 1 "}, 50 {" B ", " 2 "}}}}}, 51 } 52 53 for test, answer := range testcases { 54 dn, err := ParseDN(test) 55 if err != nil { 56 t.Errorf(err.Error()) 57 continue 58 } 59 if !reflect.DeepEqual(dn, &answer) { 60 t.Errorf("Parsed DN %s is not equal to the expected structure", test) 61 t.Logf("Expected:") 62 for _, rdn := range answer.RDNs { 63 for _, attribs := range rdn.Attributes { 64 t.Logf("#%v\n", attribs) 65 } 66 } 67 t.Logf("Actual:") 68 for _, rdn := range dn.RDNs { 69 for _, attribs := range rdn.Attributes { 70 t.Logf("#%v\n", attribs) 71 } 72 } 73 } 74 } 75 } 76 77 func TestErrorDNParsing(t *testing.T) { 78 testcases := map[string]string{ 79 "*": "DN ended with incomplete type, value pair", 80 "cn=Jim\\0Test": "failed to decode escaped character: encoding/hex: invalid byte: U+0054 'T'", 81 "cn=Jim\\0": "got corrupted escaped character", 82 "DC=example,=net": "DN ended with incomplete type, value pair", 83 // "1=#0402486": "failed to decode BER encoding: encoding/hex: odd length hex string", 84 "test,DC=example,DC=com": "incomplete type, value pair", 85 "=test,DC=example,DC=com": "incomplete type, value pair", 86 } 87 88 for test, answer := range testcases { 89 _, err := ParseDN(test) 90 if err == nil { 91 t.Errorf("Expected %s to fail parsing but succeeded\n", test) 92 } else if err.Error() != answer { 93 t.Errorf("Unexpected error on %s:\n%s\nvs.\n%s\n", test, answer, err.Error()) 94 } 95 } 96 } 97 98 func TestDNEqual(t *testing.T) { 99 testcases := []struct { 100 A string 101 B string 102 Equal bool 103 }{ 104 // Exact match 105 {"", "", true}, 106 {"o=A", "o=A", true}, 107 {"o=A", "o=B", false}, 108 109 {"o=A,o=B", "o=A,o=B", true}, 110 {"o=A,o=B", "o=A,o=C", false}, 111 112 {"o=A+o=B", "o=A+o=B", true}, 113 {"o=A+o=B", "o=A+o=C", false}, 114 115 // Case mismatch in type is ignored 116 {"o=A", "O=A", true}, 117 {"o=A,o=B", "o=A,O=B", true}, 118 {"o=A+o=B", "o=A+O=B", true}, 119 120 // Case mismatch in value is significant 121 {"o=a", "O=A", false}, 122 {"o=a,o=B", "o=A,O=B", false}, 123 {"o=a+o=B", "o=A+O=B", false}, 124 125 // Multi-valued RDN order mismatch is ignored 126 {"o=A+o=B", "O=B+o=A", true}, 127 // Number of RDN attributes is significant 128 {"o=A+o=B", "O=B+o=A+O=B", false}, 129 130 // Missing values are significant 131 {"o=A+o=B", "O=B+o=A+O=C", false}, // missing values matter 132 {"o=A+o=B+o=C", "O=B+o=A", false}, // missing values matter 133 134 // Whitespace tests 135 // Matching 136 { 137 "cn=John Doe, ou=People, dc=sun.com", 138 "cn=John Doe, ou=People, dc=sun.com", 139 true, 140 }, 141 // Difference in leading/trailing chars is ignored 142 { 143 "cn=John Doe, ou=People, dc=sun.com", 144 "cn=John Doe,ou=People,dc=sun.com", 145 true, 146 }, 147 // Difference in values is significant 148 { 149 "cn=John Doe, ou=People, dc=sun.com", 150 "cn=John Doe, ou=People, dc=sun.com", 151 false, 152 }, 153 } 154 155 for i, tc := range testcases { 156 a, err := ParseDN(tc.A) 157 if err != nil { 158 t.Errorf("%d: %v", i, err) 159 continue 160 } 161 b, err := ParseDN(tc.B) 162 if err != nil { 163 t.Errorf("%d: %v", i, err) 164 continue 165 } 166 if expected, actual := tc.Equal, a.Equal(b); expected != actual { 167 t.Errorf("%d: when comparing '%s' and '%s' expected %v, got %v", i, tc.A, tc.B, expected, actual) 168 continue 169 } 170 if expected, actual := tc.Equal, b.Equal(a); expected != actual { 171 t.Errorf("%d: when comparing '%s' and '%s' expected %v, got %v", i, tc.A, tc.B, expected, actual) 172 continue 173 } 174 } 175 } 176 177 func TestDNAncestor(t *testing.T) { 178 testcases := []struct { 179 A string 180 B string 181 Ancestor bool 182 }{ 183 // Exact match returns false 184 {"", "", false}, 185 {"o=A", "o=A", false}, 186 {"o=A,o=B", "o=A,o=B", false}, 187 {"o=A+o=B", "o=A+o=B", false}, 188 189 // Mismatch 190 {"ou=C,ou=B,o=A", "ou=E,ou=D,ou=B,o=A", false}, 191 192 // Descendant 193 {"ou=C,ou=B,o=A", "ou=E,ou=C,ou=B,o=A", true}, 194 } 195 196 for i, tc := range testcases { 197 a, err := ParseDN(tc.A) 198 if err != nil { 199 t.Errorf("%d: %v", i, err) 200 continue 201 } 202 b, err := ParseDN(tc.B) 203 if err != nil { 204 t.Errorf("%d: %v", i, err) 205 continue 206 } 207 if expected, actual := tc.Ancestor, a.AncestorOf(b); expected != actual { 208 t.Errorf("%d: when comparing '%s' and '%s' expected %v, got %v", i, tc.A, tc.B, expected, actual) 209 continue 210 } 211 } 212 }