1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2002,2008 Oracle.  All rights reserved.
5 *
6 * $Id: NegativeTest.java,v 1.1 2008/02/07 17:12:32 mark Exp $
7 */
8
9package com.sleepycat.persist.test;
10
11import java.util.ArrayList;
12
13import static com.sleepycat.persist.model.Relationship.ONE_TO_ONE;
14import junit.framework.Test;
15
16import com.sleepycat.db.DatabaseException;
17import com.sleepycat.persist.EntityStore;
18import com.sleepycat.persist.PrimaryIndex;
19import com.sleepycat.persist.StoreConfig;
20import com.sleepycat.persist.model.Entity;
21import com.sleepycat.persist.model.KeyField;
22import com.sleepycat.persist.model.Persistent;
23import com.sleepycat.persist.model.PrimaryKey;
24import com.sleepycat.persist.model.SecondaryKey;
25import com.sleepycat.util.test.TxnTestCase;
26
27/**
28 * Negative tests.
29 *
30 * @author Mark Hayes
31 */
32public class NegativeTest extends TxnTestCase {
33
34    public static Test suite() {
35        return txnTestSuite(NegativeTest.class, null, null);
36    }
37
38    private EntityStore store;
39
40    private void open()
41        throws DatabaseException {
42
43        StoreConfig config = new StoreConfig();
44        config.setAllowCreate(envConfig.getAllowCreate());
45        config.setTransactional(envConfig.getTransactional());
46
47        store = new EntityStore(env, "test", config);
48    }
49
50    private void close()
51        throws DatabaseException {
52
53        store.close();
54        store = null;
55    }
56
57    @Override
58    public void tearDown()
59        throws Exception {
60
61        if (store != null) {
62            try {
63                store.close();
64            } catch (Throwable e) {
65                System.out.println("tearDown: " + e);
66            }
67            store = null;
68        }
69        super.tearDown();
70    }
71
72    public void testBadKeyClass1()
73        throws DatabaseException {
74
75        open();
76        try {
77            PrimaryIndex<BadKeyClass1,UseBadKeyClass1> index =
78                store.getPrimaryIndex
79                    (BadKeyClass1.class, UseBadKeyClass1.class);
80            fail();
81        } catch (IllegalArgumentException expected) {
82            assertTrue(expected.getMessage().indexOf("@KeyField") >= 0);
83        }
84        close();
85    }
86
87    /** Missing @KeyField in composite key class. */
88    @Persistent
89    static class BadKeyClass1 {
90
91        private int f1;
92    }
93
94    @Entity
95    static class UseBadKeyClass1 {
96
97        @PrimaryKey
98        private BadKeyClass1 f1 = new BadKeyClass1();
99
100        @SecondaryKey(relate=ONE_TO_ONE)
101        private BadKeyClass1 f2 = new BadKeyClass1();
102    }
103
104    public void testBadSequenceKeys()
105        throws DatabaseException {
106
107        open();
108        try {
109            PrimaryIndex<Boolean,BadSequenceKeyEntity1> index =
110                store.getPrimaryIndex
111                    (Boolean.class, BadSequenceKeyEntity1.class);
112            fail();
113        } catch (IllegalArgumentException expected) {
114            assertTrue(expected.getMessage().indexOf
115                ("Type not allowed for sequence") >= 0);
116        }
117        try {
118            PrimaryIndex<BadSequenceKeyEntity2.Key,
119                         BadSequenceKeyEntity2> index =
120                store.getPrimaryIndex
121                    (BadSequenceKeyEntity2.Key.class,
122                     BadSequenceKeyEntity2.class);
123            fail();
124        } catch (IllegalArgumentException expected) {
125            assertTrue(expected.getMessage().indexOf
126                ("Type not allowed for sequence") >= 0);
127        }
128        try {
129            PrimaryIndex<BadSequenceKeyEntity3.Key,
130                         BadSequenceKeyEntity3> index =
131                store.getPrimaryIndex
132                    (BadSequenceKeyEntity3.Key.class,
133                     BadSequenceKeyEntity3.class);
134            fail();
135        } catch (IllegalArgumentException expected) {
136            assertTrue(expected.getMessage().indexOf
137                ("A composite key class used with a sequence may contain " +
138                 "only a single integer key field")>= 0);
139        }
140        close();
141    }
142
143    /** Boolean not allowed for sequence key. */
144    @Entity
145    static class BadSequenceKeyEntity1 {
146
147        @PrimaryKey(sequence="X")
148        private boolean key;
149    }
150
151    /** Composite key with non-integer field not allowed for sequence key. */
152    @Entity
153    static class BadSequenceKeyEntity2 {
154
155        @PrimaryKey(sequence="X")
156        private Key key;
157
158        @Persistent
159        static class Key {
160            @KeyField(1)
161            boolean key;
162        }
163    }
164
165    /** Composite key with multiple key fields not allowed for sequence key. */
166    @Entity
167    static class BadSequenceKeyEntity3 {
168
169        @PrimaryKey(sequence="X")
170        private Key key;
171
172        @Persistent
173        static class Key {
174            @KeyField(1)
175            int key;
176            @KeyField(2)
177            int key2;
178        }
179    }
180
181    /**
182     * A proxied object may not current contain a field that references the
183     * parent proxy.  [#15815]
184     */
185    public void testProxyNestedRef()
186        throws DatabaseException {
187
188        open();
189        PrimaryIndex<Integer,ProxyNestedRef> index = store.getPrimaryIndex
190            (Integer.class, ProxyNestedRef.class);
191        ProxyNestedRef entity = new ProxyNestedRef();
192        entity.list.add(entity.list);
193        try {
194            index.put(entity);
195            fail();
196        } catch (IllegalArgumentException expected) {
197            assertTrue(expected.getMessage().indexOf
198                ("Cannot embed a reference to a proxied object") >= 0);
199        }
200        close();
201    }
202
203    @Entity
204    static class ProxyNestedRef {
205
206        @PrimaryKey
207        private int key;
208
209        ArrayList<Object> list = new ArrayList<Object>();
210    }
211
212    /**
213     * Disallow primary keys on entity subclasses.  [#15757]
214     */
215    public void testEntitySubclassWithPrimaryKey()
216        throws DatabaseException {
217
218        open();
219        PrimaryIndex<Integer,EntitySuperClass> index = store.getPrimaryIndex
220            (Integer.class, EntitySuperClass.class);
221        EntitySuperClass e1 = new EntitySuperClass(1, "one");
222        index.put(e1);
223        assertEquals(e1, index.get(1));
224        EntitySubClass e2 = new EntitySubClass(2, "two", "foo", 9);
225        try {
226            index.put(e2);
227        } catch (IllegalArgumentException e) {
228            assertTrue(e.getMessage().contains
229                ("PrimaryKey may not appear on an Entity subclass"));
230        }
231        assertEquals(e1, index.get(1));
232        close();
233    }
234
235    @Entity
236    static class EntitySuperClass {
237
238        @PrimaryKey
239        private int x;
240
241        private String y;
242
243        EntitySuperClass(int x, String y) {
244            assert y != null;
245            this.x = x;
246            this.y = y;
247        }
248
249        private EntitySuperClass() {}
250
251        @Override
252        public String toString() {
253            return "x=" + x + " y=" + y;
254        }
255
256        @Override
257        public boolean equals(Object other) {
258            if (other instanceof EntitySuperClass) {
259                EntitySuperClass o = (EntitySuperClass) other;
260                return x == o.x && y.equals(o.y);
261            } else {
262                return false;
263            }
264        }
265    }
266
267    @Persistent
268    static class EntitySubClass extends EntitySuperClass {
269
270        @PrimaryKey
271        private String foo;
272
273        private int z;
274
275        EntitySubClass(int x, String y, String foo, int z) {
276            super(x, y);
277            assert foo != null;
278            this.foo = foo;
279            this.z = z;
280        }
281
282        private EntitySubClass() {}
283
284        @Override
285        public String toString() {
286            return super.toString() + " z=" + z;
287        }
288
289        @Override
290        public boolean equals(Object other) {
291            if (other instanceof EntitySubClass) {
292                EntitySubClass o = (EntitySubClass) other;
293                return super.equals(o) && z == o.z;
294            } else {
295                return false;
296            }
297        }
298    }
299}
300