001/*
002 * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
003 * Copyright (C) 2000-2010 The Gridarta Developers.
004 *
005 * This program is free software; you can redistribute it and/or modify
006 * it under the terms of the GNU General Public License as published by
007 * the Free Software Foundation; either version 2 of the License, or
008 * (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU General Public License for more details.
014 *
015 * You should have received a copy of the GNU General Public License along
016 * with this program; if not, write to the Free Software Foundation, Inc.,
017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
018 */
019
020package net.sf.gridarta.model.index;
021
022import java.io.File;
023import java.util.Collection;
024import java.util.HashSet;
025import java.util.Iterator;
026import java.util.TreeSet;
027import org.jetbrains.annotations.NotNull;
028import org.junit.Assert;
029import org.junit.Test;
030
031/**
032 * Regression tests for {@link MapsIndex}.
033 * @author Andreas Kirschbaum
034 */
035public class MapsIndexTest {
036
037    /**
038     * Checks that values are correctly marked as pending.
039     */
040    @Test
041    public void test1() {
042        final Index<File> index = new MapsIndex();
043        index.add(new File("a"), 1L);
044        index.add(new File("b"), 1L);
045        index.add(new File("c"), 1L);
046        Assert.assertEquals("a,b,c", getPending(index));
047        Assert.assertEquals("", getPending(index));
048        index.add(new File("d"), 1L);
049        Assert.assertEquals("d", getPending(index));
050        index.add(new File("b"), 1L);
051        index.add(new File("d"), 1L);
052        Assert.assertEquals("", getPending(index));
053        index.add(new File("b"), 2L);
054        index.add(new File("d"), 2L);
055        Assert.assertEquals("b,d", getPending(index));
056        index.setPending(new File("a"));
057        Assert.assertEquals("a", getPending(index));
058        index.setPending(new File("a"));
059        index.add(new File("b"), 3L);
060        index.add(new File("c"), 3L);
061        index.remove(new File("b"));
062        Assert.assertEquals("a,c", getPending(index));
063    }
064
065    /**
066     * Checks that {@link Index#findPartialName(String)} works as expected.
067     */
068    @Test
069    public void testFind1() {
070        final Index<File> index = new MapsIndex();
071        Assert.assertEquals("", findPartialName(index, "a"));
072        index.add(new File("abc"), 1L);
073        index.setName(new File("abc"), 1L, "abC");
074        Assert.assertEquals("abc", findPartialName(index, "a"));
075        Assert.assertEquals("abc", findPartialName(index, "b"));
076        Assert.assertEquals("", findPartialName(index, "x"));
077        index.add(new File("bcd"), 1L);
078        index.setName(new File("bcd"), 1L, "BcD");
079        Assert.assertEquals("abc", findPartialName(index, "a"));
080        Assert.assertEquals("abc,bcd", findPartialName(index, "b"));
081        Assert.assertEquals("abc,bcd", findPartialName(index, "Bc"));
082        Assert.assertEquals("", findPartialName(index, "x"));
083    }
084
085    /**
086     * Checks that {@link Index#beginUpdate()} and {@link Index#endUpdate()}
087     * works as expected.
088     */
089    @Test
090    public void testTransaction() {
091        final Index<File> index = new MapsIndex();
092        index.add(new File("a"), 1L);
093        index.add(new File("b"), 1L);
094        index.add(new File("c"), 1L);
095        index.setName(new File("a"), 2L, "a");
096        index.setName(new File("b"), 2L, "a");
097        index.setName(new File("c"), 2L, "a");
098        index.beginUpdate();
099        index.add(new File("b"), 1L);
100        index.add(new File("c"), 2L);
101        index.add(new File("d"), 2L);
102        index.endUpdate();
103        index.setName(new File("b"), 2L, "a");
104        index.setName(new File("c"), 2L, "a");
105        index.setName(new File("d"), 2L, "a");
106        Assert.assertEquals("b,c,d", findPartialName(index, "a"));
107    }
108
109    /**
110     * Checks that listeners are notified.
111     */
112    @Test
113    public void testListener() {
114        final Index<File> index = new MapsIndex();
115        final Listener listener = new Listener();
116        index.addIndexListener(listener);
117
118        index.add(new File("a"), 1L);
119        Assert.assertEquals("add a\n" + "pending changed\n", listener.getAndClearEvents());
120
121        index.add(new File("a"), 1L);
122        Assert.assertEquals("", listener.getAndClearEvents());
123
124        index.add(new File("a"), 2L);
125        Assert.assertEquals("", listener.getAndClearEvents());
126
127        index.add(new File("b"), 2L);
128        index.add(new File("c"), 2L);
129        Assert.assertEquals("add b\n" + "add c\n", listener.getAndClearEvents());
130
131        index.remove(new File("b"));
132        Assert.assertEquals("del b\n" + "name changed\n", listener.getAndClearEvents());
133
134        index.setName(new File("a"), 2L, "name1");
135        index.setName(new File("b"), 2L, "name2");
136        index.setName(new File("c"), 2L, "name3");
137        Assert.assertEquals("name changed\n" + "name changed\n" + "name changed\n", listener.getAndClearEvents());
138    }
139
140    /**
141     * Returns all pending values of a {@link MapsIndex}. Afterwards the pending
142     * entries have been removed from the index.
143     * @param index the index
144     * @return the pending values
145     */
146    @NotNull
147    private static String getPending(@NotNull final Index<File> index) {
148        final Collection<File> pendingFiles = new HashSet<File>();
149        while (true) {
150            final File pendingFile = index.removePending();
151            if (pendingFile == null) {
152                break;
153            }
154            pendingFiles.add(pendingFile);
155        }
156        return format(pendingFiles);
157    }
158
159    /**
160     * Calls {@link Index#findPartialName(String)} on the given {@link Index}
161     * and name and returns a string representation of the result.
162     * @param index the index
163     * @param name the name
164     * @return the string representation
165     */
166    @NotNull
167    private static String findPartialName(@NotNull final Index<File> index, @NotNull final String name) {
168        return format(index.findPartialName(name));
169    }
170
171    /**
172     * Returns a text representation of a {@link Collection}.
173     * @param files the collection
174     * @return the text representation
175     */
176    @NotNull
177    private static String format(@NotNull final Collection<File> files) {
178        final TreeSet<File> tmp = new TreeSet<File>(files);
179        final StringBuilder sb = new StringBuilder();
180        final Iterator<File> it = tmp.iterator();
181        if (it.hasNext()) {
182            sb.append(it.next());
183            while (it.hasNext()) {
184                sb.append(',');
185                sb.append(it.next());
186            }
187        }
188        return sb.toString();
189    }
190
191    /**
192     * An {@link IndexListener} that records a text representation of all
193     * generated events.
194     */
195    private static class Listener implements IndexListener<File> {
196
197        /**
198         * The recorded events in text representation.
199         */
200        @NotNull
201        private final StringBuilder stringBuilder = new StringBuilder();
202
203        @Override
204        public void valueAdded(@NotNull final File value) {
205            stringBuilder.append("add ").append(value).append("\n");
206        }
207
208        @Override
209        public void valueRemoved(@NotNull final File value) {
210            stringBuilder.append("del ").append(value).append("\n");
211        }
212
213        @Override
214        public void nameChanged() {
215            stringBuilder.append("name changed\n");
216        }
217
218        @Override
219        public void pendingChanged() {
220            stringBuilder.append("pending changed\n");
221        }
222
223        @Override
224        public void indexingFinished() {
225            stringBuilder.append("indexing finished");
226        }
227
228        /**
229         * Returns the accumulated events.
230         * @return the events
231         */
232        @NotNull
233        public String getAndClearEvents() {
234            final String result = stringBuilder.toString();
235            stringBuilder.setLength(0);
236            return result;
237        }
238
239    }
240
241}