Added a few tests for ARP filtering.
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / aa / arp / ArpTests.java
1 /* 
2  * The Shibboleth License, Version 1. 
3  * Copyright (c) 2002 
4  * University Corporation for Advanced Internet Development, Inc. 
5  * All rights reserved
6  * 
7  * 
8  * Redistribution and use in source and binary forms, with or without 
9  * modification, are permitted provided that the following conditions are met:
10  * 
11  * Redistributions of source code must retain the above copyright notice, this 
12  * list of conditions and the following disclaimer.
13  * 
14  * Redistributions in binary form must reproduce the above copyright notice, 
15  * this list of conditions and the following disclaimer in the documentation 
16  * and/or other materials provided with the distribution, if any, must include 
17  * the following acknowledgment: "This product includes software developed by 
18  * the University Corporation for Advanced Internet Development 
19  * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement 
20  * may appear in the software itself, if and wherever such third-party 
21  * acknowledgments normally appear.
22  * 
23  * Neither the name of Shibboleth nor the names of its contributors, nor 
24  * Internet2, nor the University Corporation for Advanced Internet Development, 
25  * Inc., nor UCAID may be used to endorse or promote products derived from this 
26  * software without specific prior written permission. For written permission, 
27  * please contact shibboleth@shibboleth.org
28  * 
29  * Products derived from this software may not be called Shibboleth, Internet2, 
30  * UCAID, or the University Corporation for Advanced Internet Development, nor 
31  * may Shibboleth appear in their name, without prior written permission of the 
32  * University Corporation for Advanced Internet Development.
33  * 
34  * 
35  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
36  * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
37  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
38  * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK 
39  * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE. 
40  * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY 
41  * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT, 
42  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
43  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
44  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
47  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  */
49
50 package edu.internet2.middleware.shibboleth.aa.arp;
51
52 import java.io.FileInputStream;
53 import java.io.InputStream;
54 import java.net.MalformedURLException;
55 import java.net.URI;
56 import java.net.URISyntaxException;
57 import java.net.URL;
58 import java.security.Principal;
59 import java.util.Arrays;
60 import java.util.HashSet;
61 import java.util.Properties;
62
63 import junit.framework.TestCase;
64
65 import org.apache.log4j.BasicConfigurator;
66 import org.apache.xerces.parsers.DOMParser;
67 import org.xml.sax.InputSource;
68
69 /**
70  * Validation suite for <code>Arp</code> processing.
71  * 
72  * @ author Walter Hoehn(wassa@columbia.edu)
73  */
74
75 public class ArpTests extends TestCase {
76
77         public ArpTests(String name) {
78                 super(name);
79                 BasicConfigurator.configure();
80         }
81
82         public static void main(String[] args) {
83                 junit.textui.TestRunner.run(ArpTests.class);
84                 BasicConfigurator.configure();
85         }
86         
87
88
89         public void testArpMarshalling() {
90
91                 //Test ARP description
92                 try {
93                         InputStream inStream = new FileInputStream("test/arp1.xml");
94                         DOMParser parser = new DOMParser();
95                         parser.parse(new InputSource(inStream));
96                         Arp arp1 = new Arp();
97                         arp1.marshall(parser.getDocument().getDocumentElement());
98                         assertEquals(
99                                 "ARP Description not marshalled properly",
100                                 arp1.getDescription(),
101                                 "Simplest possible ARP.");
102
103                         //Test Rule description
104                         assertEquals(
105                                 "ARP Rule Description not marshalled properly",
106                                 arp1.getAllRules()[0].getDescription(),
107                                 "Example Rule Description.");
108                 } catch (Exception e) {
109                         fail("Failed to marshall ARP: " + e);
110                 }
111
112                 //Test case where ARP description does not exist
113                 try {
114                         InputStream inStream = new FileInputStream("test/arp2.xml");
115                         DOMParser parser = new DOMParser();
116                         parser.parse(new InputSource(inStream));
117                         Arp arp2 = new Arp();
118                         arp2.marshall(parser.getDocument().getDocumentElement());
119                         assertNull("ARP Description not marshalled properly", arp2.getDescription());
120
121                         //Test case where ARP Rule description does not exist   
122                         assertNull(
123                                 "ARP Rule Description not marshalled properly",
124                                 arp2.getAllRules()[0].getDescription());
125                 } catch (Exception e) {
126                         fail("Failed to marshall ARP.");
127                 }
128
129         }
130
131         public void testMatchingFunctions() {
132
133                 try {
134
135                         /*
136                          * Test Arp Engine function retrieval
137                          */
138
139                         //Lookup a function that doesn't exist
140                         MatchFunction noFunction =
141                                 ArpEngine.lookupMatchFunction(new URI("urn:mace:shibboleth:arp:matchFunction:dummy"));
142                         assertNull("ArpEngine did not return null on dummy function.", noFunction);
143
144                         //Lookup some real functions
145                         MatchFunction exactSharFunction =
146                                 ArpEngine.lookupMatchFunction(new URI("urn:mace:shibboleth:arp:matchFunction:exactShar"));
147                         assertNotNull("ArpEngine did not properly load the Exact SHAR function.", exactSharFunction);
148                         MatchFunction resourceTreeFunction =
149                                 ArpEngine.lookupMatchFunction(new URI("urn:mace:shibboleth:arp:matchFunction:resourceTree"));
150                         assertNotNull(
151                                 "ArpEngine did not properly load the Resource Tree SHAR function.",
152                                 resourceTreeFunction);
153                         MatchFunction regexFunction =
154                                 ArpEngine.lookupMatchFunction(new URI("urn:mace:shibboleth:arp:matchFunction:regexMatch"));
155                         assertNotNull("ArpEngine did not properly load the Regex function.", regexFunction);
156
157                         /* 
158                          * Test the Exact SHAR function (requester)
159                          */
160
161                         assertTrue(
162                                 "Exact SHAR function: false negative",
163                                 exactSharFunction.match("shar.example.edu", "shar.example.edu"));
164                         assertTrue(
165                                 "Exact SHAR function: false negative",
166                                 !exactSharFunction.match("shar.example.edu", "www.example.edu"));
167                         assertTrue(
168                                 "Exact SHAR function: false negative",
169                                 !exactSharFunction.match("example.edu", "shar.example.edu"));
170
171                         //Make sure we properly handle bad input
172                         try {
173                                 exactSharFunction.match(null, null);
174                                 fail("Exact SHAR function seems to take improper input without throwing an exception.");
175                         } catch (ArpException ie) {
176                                 //This is supposed to fail
177                         }
178
179                         /*
180                          * Test the Resource Tree function (resource)
181                          */
182
183                         URL requestURL1 = new URL("http://www.example.edu/test/");
184                         URL requestURL2 = new URL("http://www.example.edu/test/index.html");
185                         URL requestURL3 = new URL("http://www.example.edu/test2/index.html");
186                         URL requestURL4 = new URL("http://www.example.edu/test2/index.html?test1=test1");
187
188                         assertTrue(
189                                 "Resource Tree function: false negative",
190                                 resourceTreeFunction.match("http://www.example.edu/", requestURL1));
191                         assertTrue(
192                                 "Resource Tree function: false positive",
193                                 !resourceTreeFunction.match("https://www.example.edu/", requestURL1));
194                         assertTrue(
195                                 "Resource Tree function: false negative",
196                                 resourceTreeFunction.match("http://www.example.edu:80/", requestURL1));
197                         assertTrue(
198                                 "Resource Tree function: false positive",
199                                 !resourceTreeFunction.match("http://www.example.edu:81/", requestURL1));
200                         assertTrue(
201                                 "Resource Tree function: false negative",
202                                 resourceTreeFunction.match("http://www.example.edu/test/", requestURL1));
203                         assertTrue(
204                                 "Resource Tree function: false negative",
205                                 resourceTreeFunction.match("http://www.example.edu/test/", requestURL2));
206                         assertTrue(
207                                 "Resource Tree function: false negative",
208                                 resourceTreeFunction.match("http://www.example.edu/", requestURL3));
209                         assertTrue(
210                                 "Resource Tree function: false positive",
211                                 !resourceTreeFunction.match("http://www.example.edu/test/", requestURL3));
212                         assertTrue(
213                                 "Resource Tree function: false negative",
214                                 resourceTreeFunction.match("http://www.example.edu/test2/index.html", requestURL3));
215                         assertTrue(
216                                 "Resource Tree function: false negative",
217                                 resourceTreeFunction.match("http://www.example.edu/test2/index.html", requestURL4));
218                         assertTrue(
219                                 "Resource Tree function: false negative",
220                                 resourceTreeFunction.match(
221                                         "http://www.example.edu/test2/index.html?test1=test1",
222                                         requestURL4));
223                         assertTrue(
224                                 "Resource Tree function: false positive",
225                                 !resourceTreeFunction.match(
226                                         "http://www.example.edu/test2/index.html?test1=test1",
227                                         requestURL3));
228
229                         //Make sure we properly handle bad input
230                         try {
231                                 resourceTreeFunction.match(null, null);
232                                 fail("Resource Tree function seems to take improper input without throwing an exception.");
233                         } catch (ArpException ie) {
234                                 //This is supposed to fail
235                         }
236                         try {
237                                 resourceTreeFunction.match("Test", "Test");
238                                 fail("Resource Tree function seems to take improper input without throwing an exception.");
239                         } catch (ArpException ie) {
240                                 //This is supposed to fail
241                         }
242
243                         /*
244                          * Test the Regex function (requester & resource)
245                          */
246
247                         //Try requester regexes
248                         assertTrue(
249                                 "Regex function: false negative",
250                                 regexFunction.match("^shar\\.example\\.edu$", "shar.example.edu"));
251                         assertTrue(
252                                 "Regex function: false negative",
253                                 regexFunction.match("^.*\\.example\\.edu$", "shar.example.edu"));
254                         assertTrue(
255                                 "Regex function: false negative",
256                                 regexFunction.match("^shar[1-9]?\\.example\\.edu$", "shar1.example.edu"));
257                         assertTrue("Regex function: false negative", regexFunction.match(".*\\.edu", "shar.example.edu"));
258                         assertTrue(
259                                 "Regex function: false positive",
260                                 !regexFunction.match("^shar[1-9]\\.example\\.edu$", "shar.example.edu"));
261                         assertTrue(
262                                 "Regex function: false positive",
263                                 !regexFunction.match("^shar\\.example\\.edu$", "www.example.edu"));
264                         assertTrue(
265                                 "Regex function: false positive",
266                                 !regexFunction.match("^shar\\.example\\.edu$", "www.example.com"));
267
268                         //Try resource regexes
269                         assertTrue(
270                                 "Regex function: false negative",
271                                 regexFunction.match("^http://www\\.example\\.edu/.*$", requestURL1));
272                         assertTrue(
273                                 "Regex function: false negative",
274                                 regexFunction.match("^http://www\\.example\\.edu/.*$", requestURL2));
275                         assertTrue(
276                                 "Regex function: false negative",
277                                 regexFunction.match("^http://.*\\.example\\.edu/.*$", requestURL2));
278                         assertTrue(
279                                 "Regex function: false negative",
280                                 regexFunction.match("^https?://.*\\.example\\.edu/.*$", requestURL2));
281                         assertTrue("Regex function: false negative", regexFunction.match(".*", requestURL2));
282                         assertTrue(
283                                 "Regex function: false positive",
284                                 !regexFunction.match("^https?://.*\\.example\\.edu/$", requestURL2));
285                         assertTrue(
286                                 "Regex function: false positive",
287                                 !regexFunction.match("^https?://www\\.example\\.edu/test/$", requestURL3));
288
289                         //Make sure we properly handle bad input
290                         try {
291                                 regexFunction.match(null, null);
292                                 fail("Regex function seems to take improper input without throwing an exception.");
293                         } catch (ArpException ie) {
294                                 //This is supposed to fail
295                         }
296
297                 } catch (ArpException e) {
298                         fail("Encountered a problem loading match function: " + e);
299                 } catch (URISyntaxException e) {
300                         fail("Unable to create URI from test string.");
301                 } catch (MalformedURLException e) {
302                         fail("Couldn't create test URLs: " + e);
303                 }
304
305         }
306
307         public void testRepositories() {
308
309                 /*
310                  * Test the Factory
311                  */
312
313                 //Make sure we fail if no Repository is specified
314                 Properties props = new Properties();
315                 try {
316                         ArpRepositoryFactory.getInstance(props);
317                 } catch (ArpRepositoryException e) {
318                         //This is supposed to fail
319                 }
320
321                 // Make sure we can create an Arp Repository
322                 props.setProperty(
323                         "edu.internet2.middleware.shibboleth.aa.arp.ArpRepository.implementation",
324                         "edu.internet2.middleware.shibboleth.aa.arp.provider.MemoryArpRepository");
325                 ArpRepository repository = null;
326                 try {
327                         repository = ArpRepositoryFactory.getInstance(props);
328                 } catch (ArpRepositoryException e) {
329                         fail("Failed to create memory-based Arp Repository" + e);
330                 }
331                 assertNotNull("Failed to create memory-based Arp Repository: Factory returned null.", repository);
332
333                 /*
334                  * Exercise the Memory Arp Repository
335                  */
336
337                 //Set/retrieve/remove a Site ARP
338                 Arp siteArp1 = new Arp();
339                 siteArp1.setDescription("Test Site Arp 1.");
340                 try {
341                         repository.update(siteArp1);
342                         assertEquals(
343                                 "Memory Repository does not store and retrieve Site ARPs properly.",
344                                 siteArp1,
345                                 repository.getSitePolicy());
346                         repository.remove(repository.getSitePolicy());
347                         assertNull("Memorty Repository does not properly delete Site ARPs.", repository.getSitePolicy());
348                 } catch (ArpRepositoryException e) {
349                         fail("Error adding Site ARP to Memory Repository.");
350                 }
351
352                 //Set/retrieve/delete some user ARPs
353                 Arp userArp1 = new Arp();
354                 userArp1.setDescription("Broken User Arp 1.");
355                 try {
356                         repository.update(userArp1);
357                         assertTrue(
358                                 "Memory Repository does not store and retrieve User ARPs properly.",
359                                 (!userArp1.equals(repository.getUserPolicy(userArp1.getPrincipal()))));
360                 } catch (ArpRepositoryException e) {
361                         fail("Error adding User ARP to Memory Repository.");
362                 }
363
364                 Arp userArp2 = new Arp(new AAPrincipal("TestPrincipal"));
365                 userArp2.setDescription("Test User Arp 2.");
366                 try {
367                         repository.update(userArp2);
368                         assertEquals(
369                                 "Memory Repository does not store and retrieve User ARPs properly.",
370                                 userArp2,
371                                 repository.getUserPolicy(userArp2.getPrincipal()));
372                         repository.remove(repository.getUserPolicy(userArp2.getPrincipal()));
373                         assertNull(
374                                 "Memorty Repository does not properly delete User ARPs.",
375                                 repository.getUserPolicy(userArp2.getPrincipal()));
376                 } catch (ArpRepositoryException e) {
377                         fail("Error adding User ARP to Memory Repository.");
378                 }
379
380         }
381
382         public void testPossibleReleaseSetComputation() {
383                 Properties props = new Properties();
384                 props.setProperty(
385                         "edu.internet2.middleware.shibboleth.aa.arp.ArpRepository.implementation",
386                         "edu.internet2.middleware.shibboleth.aa.arp.provider.MemoryArpRepository");
387                 ArpRepository repository = null;
388                 try {
389                         repository = ArpRepositoryFactory.getInstance(props);
390                 } catch (ArpRepositoryException e) {
391                         fail("Failed to create memory-based Arp Repository" + e);
392                 }
393
394                 try {
395                         Principal principal1 = new AAPrincipal("TestPrincipal");
396                         URL url1 = new URL("http://www.example.edu/");
397                         URI[] list1 = { new URI("urn:mace:eduPerson:1.0:eduPersonAffiliation")};
398                         URI[] list2 =
399                                 {
400                                         new URI("urn:mace:eduPerson:1.0:eduPersonAffiliation"),
401                                         new URI("urn:mace:eduPerson:1.0:eduPersonPrincipalName")};
402                         URI[] list3 = new URI[0];
403                                         
404                         //Test with just a site ARP
405                         InputStream inStream = new FileInputStream("test/arp1.xml");
406                         DOMParser parser = new DOMParser();
407                         parser.parse(new InputSource(inStream));
408                         Arp arp1 = new Arp();
409                         arp1.marshall(parser.getDocument().getDocumentElement());
410                         repository.update(arp1);
411                         ArpEngine engine = new ArpEngine(repository, props);
412                         URI[] possibleAttributes =
413                                 engine.listPossibleReleaseAttributes(principal1, "shar.example.edu", url1);
414                         assertTrue("Incorrectly computed possible release set.", Arrays.equals(possibleAttributes, list1));
415
416                         //Test with site and user ARPs
417                         inStream = new FileInputStream("test/arp7.xml");
418                         parser.parse(new InputSource(inStream));
419                         Arp arp7 = new Arp();
420                         arp7.setPrincipal(principal1);
421                         arp7.marshall(parser.getDocument().getDocumentElement());
422                         repository.update(arp7);
423                         possibleAttributes = engine.listPossibleReleaseAttributes(principal1, "shar.example.edu", url1);
424                         assertTrue("Incorrectly computed possible release set.", Arrays.equals(possibleAttributes, list2));
425                         
426                         //Ensure that explicit denies on any value are not in the release set
427                         inStream = new FileInputStream("test/arp6.xml");
428                         parser.parse(new InputSource(inStream));
429                         Arp arp6 = new Arp();
430                         arp6.setPrincipal(principal1);
431                         arp6.marshall(parser.getDocument().getDocumentElement());
432                         repository.update(arp6);
433                         possibleAttributes = engine.listPossibleReleaseAttributes(principal1, "shar.example.edu", url1);
434                         assertTrue("Incorrectly computed possible release set.", Arrays.equals(possibleAttributes, list3));
435                         
436                 } catch (Exception e) {
437                         e.printStackTrace();
438                         fail("Failed to marshall ARP: " + e);
439                 }
440
441         }
442         
443         public void testArpApplication() {
444                 Properties props = new Properties();
445                 props.setProperty(
446                         "edu.internet2.middleware.shibboleth.aa.arp.ArpRepository.implementation",
447                         "edu.internet2.middleware.shibboleth.aa.arp.provider.MemoryArpRepository");
448                 ArpRepository repository = null;
449                 try {
450                         repository = ArpRepositoryFactory.getInstance(props);
451                 } catch (ArpRepositoryException e) {
452                         fail("Failed to create memory-based Arp Repository" + e);
453                 }
454                 try {
455                         Principal principal1 = new AAPrincipal("TestPrincipal");
456                         URL url1 = new URL("http://www.example.edu/");
457
458                         //Test with just a site ARP
459                         InputStream inStream = new FileInputStream("test/arp1.xml");
460                         DOMParser parser = new DOMParser();
461                         parser.parse(new InputSource(inStream));
462                         Arp arp1 = new Arp();
463                         arp1.marshall(parser.getDocument().getDocumentElement());
464                         repository.update(arp1);
465                         ArpEngine engine = new ArpEngine(repository, props);
466
467                         TestAttribute testAttribute1 =
468                                 new TestAttribute(
469                                         "urn:mace:eduPerson:1.0:eduPersonAffiliation",
470                                         new Object[] { "member@example.edu", "faculty@example.edu" });
471                         TestAttribute testAttribute2 =
472                                 new TestAttribute(
473                                         "urn:mace:eduPerson:1.0:eduPersonPrincipalName",
474                                         new Object[] { "mehoehn@example.edu" });
475                         ArpAttribute[] releaseAttributes =
476                                 engine.filterAttributes(
477                                         new ArpAttribute[] { testAttribute1, testAttribute2 },
478                                         principal1,
479                                         "shar.example.edu",
480                                         url1);
481                         assertEquals(
482                                 "ARP not applied as expected.",
483                                 new HashSet(Arrays.asList(releaseAttributes)),
484                                 new HashSet(Arrays.asList(new ArpAttribute[] { testAttribute1 })));
485
486                         //Test with site and user ARPs
487                         inStream = new FileInputStream("test/arp7.xml");
488                         parser.parse(new InputSource(inStream));
489                         Arp arp7 = new Arp();
490                         arp7.setPrincipal(principal1);
491                         arp7.marshall(parser.getDocument().getDocumentElement());
492                         repository.update(arp7);
493                         releaseAttributes =
494                                 engine.filterAttributes(
495                                         new ArpAttribute[] { testAttribute1, testAttribute2 },
496                                         principal1,
497                                         "shar.example.edu",
498                                         url1);
499                         assertEquals(
500                                 "ARP not applied as expected.",
501                                 new HashSet(Arrays.asList(releaseAttributes)),
502                                 new HashSet(Arrays.asList(new ArpAttribute[] { testAttribute1, testAttribute2 })));
503
504                         //Test with site and user ARPs
505                         releaseAttributes =
506                                 engine.filterAttributes(
507                                         new ArpAttribute[] { testAttribute1, testAttribute2 },
508                                         principal1,
509                                         "shar1.example.edu",
510                                         url1);
511                         assertEquals(
512                                 "ARP not applied as expected.",
513                                 new HashSet(Arrays.asList(releaseAttributes)),
514                                 new HashSet(Arrays.asList(new ArpAttribute[] { testAttribute1 })));
515
516                         //Test with site and user ARPs
517                         inStream = new FileInputStream("test/arp6.xml");
518                         parser.parse(new InputSource(inStream));
519                         Arp arp6 = new Arp();
520                         arp6.setPrincipal(principal1);
521                         arp6.marshall(parser.getDocument().getDocumentElement());
522                         repository.update(arp6);
523                         releaseAttributes =
524                                 engine.filterAttributes(
525                                         new ArpAttribute[] { testAttribute1, testAttribute2 },
526                                         principal1,
527                                         "shar.example.edu",
528                                         url1);
529                         assertEquals(
530                                 "ARP not applied as expected.",
531                                 new HashSet(Arrays.asList(releaseAttributes)),
532                                 new HashSet());
533
534                 } catch (Exception e) {
535                         e.printStackTrace();
536                         fail("Failed to apply ARPs: " + e);
537                 }
538         }
539         
540         public class TestAttribute implements ArpAttribute {
541                 private String name;
542                 private Object[] values;
543
544                 public TestAttribute(String name, Object[] values) {
545                         this.name = name;
546                         this.values = values;
547                 }
548
549                 /**
550                  * @see edu.internet2.middleware.shibboleth.aa.arp.ArpAttribute#getName()
551                  */
552                 public String getName() {
553                         return name;
554                 }
555
556                 /**
557                  * @see edu.internet2.middleware.shibboleth.aa.arp.ArpAttribute#getValues()
558                  */
559                 public Object[] getValues() {
560                         return values;
561                 }
562
563                 /**
564                  * @see edu.internet2.middleware.shibboleth.aa.arp.ArpAttribute#setValues(Object[])
565                  */
566                 public void setValues(Object[] values) {
567                         this.values = values;
568                 }
569
570                 public boolean equals(Object object) {
571                         if (!(object instanceof TestAttribute)) {
572                                 return false;
573                         }
574                         //finish this
575                         return (new HashSet(Arrays.asList(values))).equals(
576                                 Arrays.asList(((TestAttribute) object).getValues()));
577                 }
578
579         }
580
581 }