| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.netbeans.modules.javascript.bower.file; |
| |
| import java.beans.PropertyChangeEvent; |
| import java.beans.PropertyChangeListener; |
| import java.io.File; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.io.Writer; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.concurrent.CountDownLatch; |
| import java.util.concurrent.ExecutorService; |
| import java.util.concurrent.Executors; |
| import java.util.concurrent.TimeUnit; |
| import org.json.simple.JSONObject; |
| import org.junit.Assert; |
| import org.netbeans.junit.NbTestCase; |
| import org.openide.filesystems.FileObject; |
| import org.openide.filesystems.FileUtil; |
| |
| import static junit.framework.Assert.assertEquals; |
| import static junit.framework.Assert.assertFalse; |
| import static junit.framework.Assert.assertNotNull; |
| import static junit.framework.Assert.assertNull; |
| import static junit.framework.Assert.assertTrue; |
| import static junit.framework.Assert.fail; |
| |
| public class BowerJsonTest extends NbTestCase { |
| |
| private static final ExecutorService EXECUTORS = Executors.newCachedThreadPool(); |
| |
| private FileObject directory; |
| private BowerJson bowerJson; |
| |
| |
| public BowerJsonTest(String name) { |
| super(name); |
| } |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| clearWorkDir(); |
| File dummy = new File(getWorkDir(), "dummy"); |
| assertTrue(dummy.mkdir()); |
| directory = FileUtil.toFileObject(dummy); |
| assertNotNull(directory); |
| bowerJson = new BowerJson(directory); |
| } |
| |
| @Override |
| protected void tearDown() throws Exception { |
| super.tearDown(); |
| bowerJson.cleanup(); |
| } |
| |
| public void testNoBowerJson() { |
| assertFalse(bowerJson.exists()); |
| assertEquals(getFile().getAbsolutePath(), bowerJson.getPath()); |
| } |
| |
| public void testBowerJson() throws Exception { |
| writeFile(getData(true, false)); |
| assertTrue(bowerJson.exists()); |
| assertEquals(getFile().getAbsolutePath(), bowerJson.getPath()); |
| } |
| |
| public void testDependencies() throws Exception { |
| BowerJson invalidBowerJson = new BowerJson(FileUtil.toFileObject(getDataDir()), "invalid-bower.json"); |
| assertTrue(invalidBowerJson.getFile().getAbsolutePath(), invalidBowerJson.exists()); |
| BowerJson.BowerDependencies dependencies = invalidBowerJson.getDependencies(); |
| assertEquals(14, dependencies.getCount()); |
| assertEquals(7, dependencies.dependencies.size()); |
| assertEquals(7, dependencies.devDependencies.size()); |
| Map<String, String> expectedDependencies = new HashMap<>(); |
| expectedDependencies.put("a/b", "1.13.1"); |
| expectedDependencies.put("c/d", "1"); |
| expectedDependencies.put("e/f", "1.5"); |
| expectedDependencies.put("g/h", "null"); |
| expectedDependencies.put("i/j", "true"); |
| expectedDependencies.put("k/l", "{myver=123}"); |
| expectedDependencies.put("m/n", "[1, 2]"); |
| assertEquals(expectedDependencies, dependencies.dependencies); |
| Map<String, String> expectedDevDependencies = new HashMap<>(); |
| expectedDevDependencies.put("aa/bb", "42"); |
| expectedDevDependencies.put("cc/dd", "1"); |
| expectedDevDependencies.put("ee/ff", "1.5"); |
| expectedDevDependencies.put("gg/hh", "null"); |
| expectedDevDependencies.put("ii/jj", "true"); |
| expectedDevDependencies.put("kk/ll", "{myver=123}"); |
| expectedDevDependencies.put("mm/nn", "[1, 2]"); |
| assertEquals(expectedDevDependencies, dependencies.devDependencies); |
| } |
| |
| public void testDependenciesChange() throws Exception { |
| CountDownLatch countDownLatch1 = new CountDownLatch(1); |
| PropertyChangeListenerImpl listener = new PropertyChangeListenerImpl(); |
| listener.setCountDownLatch(countDownLatch1); |
| bowerJson.addPropertyChangeListener(listener); |
| Map<String, Object> data = getData(true, false); |
| asyncWriteFile(data); |
| // wait |
| countDownLatch1.await(1, TimeUnit.MINUTES); |
| // needed for FS to notice the change |
| Thread.sleep(1000); |
| // change content |
| CountDownLatch countDownLatch2 = new CountDownLatch(1); |
| listener.setCountDownLatch(countDownLatch2); |
| Map<String, Object> newData = getData(true, true); |
| newData.put(BowerJson.FIELD_DEPENDENCIES, Collections.singletonMap("http://example.com/script.js", "1.0")); |
| asyncWriteFile(newData); |
| // wait |
| countDownLatch2.await(1, TimeUnit.MINUTES); |
| // needed for FS to notice the change |
| Thread.sleep(1000); |
| // check events |
| Map<String, List<PropertyChangeEvent>> allEvents = listener.getAllEvents(); |
| assertEquals(2, allEvents.size()); |
| // dependencies |
| List<PropertyChangeEvent> depEvents = allEvents.get(BowerJson.PROP_DEPENDENCIES); |
| assertNotNull(depEvents); |
| assertEquals(2, depEvents.size()); |
| PropertyChangeEvent event = depEvents.get(0); |
| assertEquals(BowerJson.PROP_DEPENDENCIES, event.getPropertyName()); |
| assertNull(event.getOldValue()); |
| assertEquals(data.get(BowerJson.FIELD_DEPENDENCIES), event.getNewValue()); |
| event = depEvents.get(1); |
| assertEquals(BowerJson.PROP_DEPENDENCIES, event.getPropertyName()); |
| assertEquals(data.get(BowerJson.FIELD_DEPENDENCIES), event.getOldValue()); |
| assertEquals(newData.get(BowerJson.FIELD_DEPENDENCIES), event.getNewValue()); |
| // devDependencies |
| List<PropertyChangeEvent> devDepEvents = allEvents.get(BowerJson.PROP_DEV_DEPENDENCIES); |
| assertNotNull(devDepEvents); |
| assertEquals(1, devDepEvents.size()); |
| event = devDepEvents.get(0); |
| assertEquals(BowerJson.PROP_DEV_DEPENDENCIES, event.getPropertyName()); |
| assertNull(event.getOldValue()); |
| assertEquals(newData.get(BowerJson.FIELD_DEV_DEPENDENCIES), event.getNewValue()); |
| } |
| |
| private File getFile() { |
| return new File(FileUtil.toFile(directory), BowerJson.FILE_NAME); |
| } |
| |
| private Map<String, Object> getData(boolean dependencies, boolean devDependencies) { |
| Map<String, Object> data = new LinkedHashMap<>(); |
| if (dependencies) { |
| Map<String, Object> deps = new LinkedHashMap<>(); |
| deps.put("jquery", "*"); |
| data.put(BowerJson.FIELD_DEPENDENCIES, deps); |
| } |
| if (devDependencies) { |
| Map<String, Object> devDeps = new LinkedHashMap<>(); |
| devDeps.put("jasmine", "*"); |
| data.put(BowerJson.FIELD_DEV_DEPENDENCIES, devDeps); |
| } |
| return data; |
| } |
| |
| private void writeFile(Map<String, Object> data) throws IOException { |
| File file = getFile(); |
| try (Writer out = new FileWriter(file)) { |
| JSONObject.writeJSONString(data, out); |
| } |
| assertTrue(file.isFile()); |
| refreshForFile(file); |
| } |
| |
| private void asyncWriteFile(Map<String, Object> data) { |
| final Map<String, Object> synchronizedData = Collections.synchronizedMap(data); |
| EXECUTORS.submit(new Runnable() { |
| @Override |
| public void run() { |
| try { |
| writeFile(synchronizedData); |
| } catch (IOException ex) { |
| fail(ex.getMessage()); |
| } |
| } |
| }); |
| } |
| |
| private void refreshForFile(File file) { |
| FileUtil.refreshFor(file.getParentFile()); |
| } |
| |
| //~ Inner classes |
| |
| private static final class PropertyChangeListenerImpl implements PropertyChangeListener { |
| |
| private final Map<String, List<PropertyChangeEvent>> allEvents = new HashMap<>(); |
| private volatile CountDownLatch countDownLatch; |
| |
| |
| public void setCountDownLatch(CountDownLatch countDownLatch) { |
| this.countDownLatch = countDownLatch; |
| } |
| |
| @Override |
| public synchronized void propertyChange(PropertyChangeEvent evt) { |
| Assert.assertNotNull(evt); |
| String propertyName = evt.getPropertyName(); |
| Assert.assertNotNull(propertyName); |
| List<PropertyChangeEvent> events = allEvents.get(propertyName); |
| if (events == null) { |
| events = new ArrayList<>(); |
| allEvents.put(propertyName, events); |
| } |
| events.add(evt); |
| countDownLatch.countDown(); |
| } |
| |
| public Map<String, List<PropertyChangeEvent>> getAllEvents() { |
| return new HashMap<>(allEvents); |
| } |
| |
| } |
| |
| } |