/******************************************************************************** | |
* Copyright (c) 2015-2019 Contributors to the Eclipse Foundation | |
* | |
* See the NOTICE file(s) distributed with this work for additional | |
* information regarding copyright ownership. | |
* | |
* This program and the accompanying materials are made available under the | |
* terms of the Eclipse Public License v. 2.0 which is available at | |
* http://www.eclipse.org/legal/epl-2.0. | |
* | |
* SPDX-License-Identifier: EPL-2.0 | |
* | |
********************************************************************************/ | |
package org.eclipse.mdm.businessobjects.boundary; | |
import static org.hamcrest.Matchers.equalTo; | |
import static org.hamcrest.Matchers.hasItems; | |
import static org.mockito.ArgumentMatchers.any; | |
import static org.mockito.ArgumentMatchers.eq; | |
import static org.mockito.Mockito.mock; | |
import static org.mockito.Mockito.when; | |
import java.io.ByteArrayInputStream; | |
import java.io.IOException; | |
import java.util.Collection; | |
import java.util.Map; | |
import java.util.Optional; | |
import javax.ejb.EJB; | |
import javax.inject.Inject; | |
import javax.inject.Singleton; | |
import javax.ws.rs.core.Application; | |
import org.eclipse.mdm.api.base.adapter.ChildrenStore; | |
import org.eclipse.mdm.api.base.adapter.Core; | |
import org.eclipse.mdm.api.base.adapter.EntityStore; | |
import org.eclipse.mdm.api.base.adapter.RelationStore; | |
import org.eclipse.mdm.api.base.file.FileService; | |
import org.eclipse.mdm.api.base.model.ContextType; | |
import org.eclipse.mdm.api.base.model.Entity; | |
import org.eclipse.mdm.api.base.model.Enumeration; | |
import org.eclipse.mdm.api.base.model.FileLink; | |
import org.eclipse.mdm.api.base.model.MimeType; | |
import org.eclipse.mdm.api.base.model.Test; | |
import org.eclipse.mdm.api.base.model.User; | |
import org.eclipse.mdm.api.base.model.Value; | |
import org.eclipse.mdm.api.base.model.ValueType; | |
import org.eclipse.mdm.api.dflt.ApplicationContext; | |
import org.eclipse.mdm.api.dflt.model.EntityFactory; | |
import org.eclipse.mdm.api.dflt.model.Pool; | |
import org.eclipse.mdm.api.dflt.model.Project; | |
import org.eclipse.mdm.businessobjects.control.FileLinkActivity; | |
import org.eclipse.mdm.businessobjects.service.EntityService; | |
import org.eclipse.mdm.connector.boundary.ConnectorService; | |
import org.glassfish.hk2.api.Factory; | |
import org.glassfish.hk2.api.Injectee; | |
import org.glassfish.hk2.api.InjectionResolver; | |
import org.glassfish.hk2.api.ServiceHandle; | |
import org.glassfish.hk2.api.ServiceLocator; | |
import org.glassfish.hk2.api.TypeLiteral; | |
import org.glassfish.hk2.utilities.binding.AbstractBinder; | |
import org.glassfish.jersey.server.ResourceConfig; | |
import org.glassfish.jersey.test.JerseyTest; | |
import org.junit.Before; | |
import com.google.common.collect.ImmutableMap; | |
import io.restassured.RestAssured; | |
import io.vavr.control.Try; | |
public class FileLinkActivityTest extends JerseyTest { | |
public static final String ENV = "MDM"; | |
public static final FileLink[] FILE_LINKS = new FileLink[] { | |
FileLink.newRemote("dir/test.txt", new MimeType("text/plain"), "Just a text file"), | |
FileLink.newRemote("dir/subdir/test.bin", new MimeType("application/octet-stream"), "A binary file"), | |
FileLink.newRemote("dir/specialCharsßä#&'.bin", new MimeType("application/octet-stream"), | |
"A binary file") }; | |
private ConnectorService connectorService = mock(ConnectorService.class); | |
private ApplicationContext context = mock(ApplicationContext.class); | |
private FileService fileService = mock(FileService.class); | |
private EntityService entityService = mock(EntityService.class); | |
@Override | |
protected Application configure() { | |
AbstractBinder binder = new AbstractBinder() { | |
@Override | |
protected void configure() { | |
bind(EJBInjectResolver.class).to(new TypeLiteral<InjectionResolver<EJB>>() { | |
}).in(Singleton.class); | |
bind(TestService.class).to(TestService.class); | |
bindFactory(new InstanceFactory<EntityService>(entityService)).to(EntityService.class); | |
bindFactory(new InstanceFactory<ConnectorService>(connectorService)).to(ConnectorService.class); | |
bind(FileLinkActivity.class).to(FileLinkActivity.class); | |
} | |
}; | |
return new ResourceConfig(TestResource.class, TestStepResource.class, MeasurementResource.class) | |
.register(binder); | |
} | |
@Before | |
public void init() throws IOException { | |
RestAssured.baseURI = target().getUri().toString(); | |
final Test test = createTest(FILE_LINKS); | |
when(entityService.find(any(), eq(Test.class), any())).thenReturn(Try.of(() -> test)); | |
when(connectorService.getContextByName(eq(ENV))).thenReturn(context); | |
when(context.getFileService()).thenReturn(Optional.of(fileService)); | |
when(fileService.openStream(eq(test), eq(FILE_LINKS[0]))) | |
.thenReturn(new ByteArrayInputStream("Some text".getBytes())); | |
when(fileService.openStream(eq(test), eq(FILE_LINKS[2]))) | |
.thenReturn(new ByteArrayInputStream("xyz".getBytes())); | |
} | |
@org.junit.Test | |
public void testMDMLinksAttribute() { | |
// request test and check MDMLinks attribute | |
RestAssured.given().pathParam("SOURCENAME", ENV).pathParam("TESTID", "1").when() | |
.get("/environments/{SOURCENAME}/tests/{TESTID}").then().statusCode(200) | |
.body("data.get(0).attributes.find { it.get('name') == 'MDMLinks' }.value.remotePath", | |
hasItems("dir/test.txt", "dir/subdir/test.bin", "dir/specialCharsßä#&'.bin")) | |
.and() | |
.body("data.get(0).attributes.find { it.get('name') == 'MDMLinks' }.value.description", | |
hasItems("Just a text file", "A binary file", "A binary file")) | |
.and().body("data.get(0).attributes.find { it.get('name') == 'MDMLinks' }.value.mimeType", | |
hasItems("text/plain", "application/octet-stream", "application/octet-stream")); | |
} | |
@org.junit.Test | |
public void testFileDownload() { | |
RestAssured.given().pathParam("SOURCENAME", ENV).pathParam("TESTID", "1") | |
.pathParam("REMOTE_PATH", "dir/test.txt").when() | |
.get("/environments/{SOURCENAME}/tests/{TESTID}/files/{REMOTE_PATH}").then().statusCode(200) | |
.contentType("text/plain").body(equalTo("Some text")); | |
} | |
@org.junit.Test | |
public void testFileDownloadWithSpecialChars() { | |
RestAssured.given().pathParam("SOURCENAME", ENV).pathParam("TESTID", "1") | |
.pathParam("REMOTE_PATH", "dir/specialCharsßä#&'.bin").when() | |
.get("/environments/{SOURCENAME}/tests/{TESTID}/files/{REMOTE_PATH}").then().statusCode(200) | |
.contentType("application/octet-stream").body(equalTo("xyz")); | |
} | |
private Test createTest(FileLink[] fileLinks) { | |
EntityFactory factory = new JUnitEntityFactory() { | |
@Override | |
protected <T extends Entity> Core createCore(Class<T> entityClass) { | |
return new CoreImpl(ImmutableMap.of("Name", ValueType.STRING.create("test"), "DateCreated", | |
ValueType.DATE.create("DateCreated"), "MDMLinks", | |
ValueType.FILE_LINK_SEQUENCE.create("MDMLinks", fileLinks))); | |
} | |
}; | |
final Project project = factory.createProject("MyProject"); | |
final Pool pool = factory.createPool("MyPool", project); | |
return factory.createTest("MyTest", pool); | |
} | |
public static class EJBInjectResolver implements InjectionResolver<EJB> { | |
@Inject | |
private ServiceLocator locator; | |
@Override | |
public Object resolve(Injectee injectee, ServiceHandle<?> root) { | |
return locator.getService(injectee.getRequiredType()); | |
} | |
@Override | |
public boolean isConstructorParameterIndicator() { | |
return false; | |
} | |
@Override | |
public boolean isMethodParameterIndicator() { | |
return false; | |
} | |
} | |
private class JUnitEntityFactory extends EntityFactory { | |
@Override | |
protected Optional<User> getLoggedInUser() { | |
return Optional.empty(); | |
} | |
@Override | |
protected <T extends Entity> Core createCore(Class<T> entityClass) { | |
// noop | |
return null; | |
} | |
@Override | |
protected void validateEnum(Enumeration<?> enumerationObj) { | |
// noop | |
} | |
@Override | |
protected <T extends Entity> Core createCore(Class<T> entityClass, ContextType contextType) { | |
// noop | |
return null; | |
} | |
@Override | |
protected <T extends Entity> Core createCore(String name, Class<T> entityClass) { | |
// noop | |
return null; | |
} | |
} | |
public class InstanceFactory<T> implements Factory<T> { | |
private T instance; | |
public InstanceFactory(T instance) { | |
this.instance = instance; | |
} | |
@Override | |
public void dispose(T t) { | |
} | |
@Override | |
public T provide() { | |
return instance; | |
} | |
} | |
public class CoreImpl implements Core { | |
private Map<String, Value> values; | |
private EntityStore mutableStore; | |
public CoreImpl(Map<String, Value> values) { | |
super(); | |
this.values = values; | |
this.mutableStore = new EntityStore(); | |
} | |
@Override | |
public String getSourceName() { | |
return "UnitTestSource"; | |
} | |
@Override | |
public String getTypeName() { | |
return "UnitTestType"; | |
} | |
@Override | |
public String getID() { | |
return "4711l"; | |
} | |
@Override | |
public void setID(String instanceID) { | |
} | |
@Override | |
public Map<String, Value> getValues() { | |
return values; | |
} | |
@Override | |
public void hideValues(Collection<String> names) { | |
} | |
@Override | |
public Map<String, Value> getAllValues() { | |
return values; | |
} | |
@Override | |
public EntityStore getMutableStore() { | |
return mutableStore; | |
} | |
@Override | |
public EntityStore getPermanentStore() { | |
return new EntityStore(); | |
} | |
@Override | |
public ChildrenStore getChildrenStore() { | |
return new ChildrenStore(); | |
} | |
@Override | |
public RelationStore getNtoMStore() { | |
return new RelationStore(); | |
} | |
} | |
} |