1   package org.apache.torque.engine.database.model;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.Arrays;
24  import java.util.List;
25  
26  import org.apache.torque.engine.EngineException;
27  
28  import junit.framework.TestCase;
29  
30  /***
31   * <p>Unit tests for class <code>NameFactory</code> and known
32   * <code>NameGenerator</code> implementations.</p>
33   *
34   * <p>To add more tests, add entries to the <code>ALGORITHMS</code>,
35   * <code>INPUTS</code>, and <code>OUTPUTS</code> arrays, and code to
36   * the <code>makeInputs()</code> method.</p>
37   *
38   * <p>This test assumes that it's being run using the MySQL database
39   * adapter, <code>DBMM</code>.  MySQL has a column length limit of 64
40   * characters.</p>
41   *
42   * @author <a href="mailto:dlr@collab.net">Daniel Rall</a>
43   * @version $Id: NameFactoryTest.java 473814 2006-11-11 22:30:30Z tv $
44   */
45  public class NameFactoryTest extends TestCase
46  {
47  
48      /*** The database to mimic in generating the SQL. */
49      private static final String DATABASE_TYPE = "mysql";
50  
51      /***
52       * The list of known name generation algorithms, specified as the
53       * fully qualified class names to <code>NameGenerator</code>
54       * implementations.
55       */
56      private static final String[] ALGORITHMS =
57          { NameFactory.CONSTRAINT_GENERATOR, NameFactory.JAVA_GENERATOR };
58  
59      /***
60       * Two dimensional arrays of inputs for each algorithm.
61       */
62      private static final Object[][][] INPUTS =
63          { { { makeString(61), "I", new Integer(1)}, {
64                  makeString(61), "I", new Integer(2)
65                  }, {
66                  makeString(65), "I", new Integer(3)
67                  }, {
68                  makeString(4), "FK", new Integer(1)
69                  }, {
70                  makeString(5), "FK", new Integer(2)
71                  }
72          }, {
73              {
74                  "MY_USER",
75                          NameGenerator.CONV_METHOD_UNDERSCORE }, {
76                  "MY_USER",
77                          NameGenerator.CONV_METHOD_UNDERSCORE_OMIT_SCHEMA }, {
78                  "MY_USER",
79                          NameGenerator.CONV_METHOD_JAVANAME }, {
80                  "MY_USER",
81                          NameGenerator.CONV_METHOD_NOCHANGE }, {
82                  "MY_SCHEMA.MY_USER",
83                          NameGenerator.CONV_METHOD_UNDERSCORE }, {
84                  "MY_SCHEMA.MY_USER",
85                          NameGenerator.CONV_METHOD_UNDERSCORE_OMIT_SCHEMA }, {
86                  "MY_SCHEMA.MY_USER",
87                          NameGenerator.CONV_METHOD_JAVANAME } , {
88                  "MY_SCHEMA.MY_USER",
89                          NameGenerator.CONV_METHOD_NOCHANGE }
90          }
91      };
92  
93      /***
94       * Given the known inputs, the expected name outputs.
95       */
96      private static final String[][] OUTPUTS =
97          {
98              {
99                  makeString(60) + "_I_1",
100                 makeString(60) + "_I_2",
101                 makeString(60) + "_I_3",
102                 makeString(4) + "_FK_1",
103                 makeString(5) + "_FK_2" },
104             {
105                 "MyUser",
106                 "MyUser",
107                 "MYUSER",
108                 "MY_USER",
109                 "MySchemaMyUser",
110                 "MyUser",
111                 "MYSCHEMAMYUSER",
112                 "MY_SCHEMA.MY_USER"
113             }
114     };
115 
116     /***
117      * Used as an input.
118      */
119     private Database database;
120 
121     /***
122      * Creates a new instance.
123      *
124      * @param name the name of the test to run
125      */
126     public NameFactoryTest(String name)
127     {
128         super(name);
129     }
130 
131     /***
132      * Creates a string of the specified length consisting entirely of
133      * the character <code>A</code>.  Useful for simulating table
134      * names, etc.
135      *
136      * @param len the number of characters to include in the string
137      * @return a string of length <code>len</code> with every character an 'A'
138      */
139     private static final String makeString(int len)
140     {
141         StringBuffer buf = new StringBuffer();
142         for (int i = 0; i < len; i++)
143         {
144             buf.append('A');
145         }
146         return buf.toString();
147     }
148 
149     /*** Sets up the Torque model. */
150     public void setUp()
151     {
152         database = new Database(DATABASE_TYPE);
153         database.setDatabaseType(DATABASE_TYPE);
154     }
155 
156     /***
157      * @throws Exception on fail
158      */
159     public void testNames() throws Exception
160     {
161         for (int algoIndex = 0; algoIndex < ALGORITHMS.length; algoIndex++)
162         {
163             String algo = ALGORITHMS[algoIndex];
164             Object[][] algoInputs = INPUTS[algoIndex];
165             for (int i = 0; i < algoInputs.length; i++)
166             {
167                 List inputs = makeInputs(algo, algoInputs[i]);
168                 String generated = NameFactory.generateName(algo, inputs);
169                 String expected = OUTPUTS[algoIndex][i];
170                 assertEquals(
171                     "Algorithm " + algo + " failed to generate an unique name",
172                     generated,
173                     expected);
174             }
175         }
176     }
177 
178     /***
179      * @throws Exception on fail
180      */
181     public void testException() throws Exception
182     {
183         try
184         {
185             NameFactory.generateName("non.existing.class", new ArrayList());
186             assertTrue("Expected an EngineException", false);
187         }
188         catch (EngineException ex)
189         {
190         }
191     }
192 
193     /***
194      * Creates the list of arguments to pass to the specified type of
195      * <code>NameGenerator</code> implementation.
196      *
197      * @param algo The class name of the <code>NameGenerator</code> to
198      * create an argument list for.
199      * @param inputs The (possibly partial) list inputs from which to
200      * generate the final list.
201      * @return the list of arguments to pass to the <code>NameGenerator</code>
202      */
203     private final List makeInputs(String algo, Object[] inputs)
204     {
205         List list = null;
206         if (NameFactory.CONSTRAINT_GENERATOR.equals(algo))
207         {
208             list = new ArrayList(inputs.length + 1);
209             list.add(0, database);
210             list.addAll(Arrays.asList(inputs));
211         }
212         else if (NameFactory.JAVA_GENERATOR.equals(algo))
213         {
214             list = Arrays.asList(inputs);
215         }
216         return list;
217     }
218 
219 }