/*
* Copyright (c) 2013-2015 Evolveum
*
* Licensed 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 com.evolveum.midpoint.testing.wstest;
import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
import com.evolveum.midpoint.model.client.ModelClientUtil;
import com.evolveum.midpoint.test.util.LogfileTestTailer;
import com.evolveum.midpoint.test.util.TestUtil;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.GetOperationOptionsType;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectDeltaListType;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectDeltaOperationListType;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.ObjectListType;
import com.evolveum.midpoint.xml.ns._public.common.api_types_3.SelectorQualifiedGetOptionsType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import com.evolveum.midpoint.xml.ns._public.model.model_3.ModelPortType;
import com.evolveum.midpoint.xml.ns._public.model.model_3.ModelService;
import com.evolveum.midpoint.xml.ns._public.common.fault_3.FaultMessage;
import com.evolveum.midpoint.xml.ns._public.common.fault_3.FaultType;
import com.evolveum.prism.xml.ns._public.query_3.PagingType;
import com.evolveum.prism.xml.ns._public.types_3.ChangeTypeType;
import com.evolveum.prism.xml.ns._public.types_3.ItemDeltaType;
import com.evolveum.prism.xml.ns._public.types_3.ModificationTypeType;
import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType;
import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.BooleanUtils;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.service.model.EndpointInfo;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.handler.WSHandlerConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.AssertJUnit;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import org.w3c.dom.*;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.soap.SOAPFault;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Holder;
import javax.xml.ws.soap.SOAPFaultException;
/**
* Test Framework Util Class
*
* <p>
* This class contains static methods and functionality needed
* across all test suites in this framework
* It takes care of initialization of modelPort - webService client,
* which is used to communicate with midpoint in all tests
* </p>
*
*
* @author semancik
* @author Erik Suta
*
* */
public abstract class AbstractWebserviceTest {
protected static final Trace LOGGER = TraceManager.getTrace(AbstractWebserviceTest.class);
public static final File COMMON_DIR = new File("src/test/resources/common");
public static final String ENDPOINT = "http://localhost:8080/midpoint/ws/model-3";
public static final String USER_ADMINISTRATOR_OID = SystemObjectsType.USER_ADMINISTRATOR.value();
public static final String USER_ADMINISTRATOR_USERNAME = "administrator";
public static final String USER_ADMINISTRATOR_PASSWORD = "5ecr3t";
public static final File USER_JACK_FILE = new File(COMMON_DIR, "user-jack.xml");
public static final String USER_JACK_OID = "c0c010c0-d34d-b33f-f00d-111111111111";
public static final String USER_JACK_USERNAME = "jack";
public static final String USER_JACK_GIVEN_NAME = "Jack";
public static final String USER_JACK_FAMILY_NAME = "Sparrow";
// No authorization
public static final File USER_NOBODY_FILE = new File(COMMON_DIR, "user-nobody.xml");
public static final String USER_NOBODY_USERNAME = "nobody";
public static final String USER_NOBODY_GIVEN_NAME = "No";
public static final String USER_NOBODY_FAMILY_NAME = "Body";
public static final String USER_NOBODY_PASSWORD = "nopassword";
// WS authorization only
public static final File USER_CYCLOPS_FILE = new File(COMMON_DIR, "user-cyclops.xml");
public static final String USER_CYCLOPS_USERNAME = "cyclops";
public static final String USER_CYCLOPS_PASSWORD = "cyclopassword";
// WS and reader authorization
public static final File USER_SOMEBODY_FILE = new File(COMMON_DIR, "user-somebody.xml");
public static final String USER_SOMEBODY_USERNAME = "somebody";
public static final String USER_SOMEBODY_PASSWORD = "somepassword";
// WS, reader and adder authorization
public static final File USER_DARTHADDER_FILE = new File(COMMON_DIR, "user-darthadder.xml");
public static final String USER_DARTHADDER_OID = "1696229e-d90a-11e4-9ce6-001e8c717e5b";
public static final String USER_DARTHADDER_USERNAME = "darthadder";
public static final String USER_DARTHADDER_PASSWORD = "iamyouruncle";
// Authorizations, but no password
public static final File USER_NOPASSWORD_FILE = new File(COMMON_DIR, "user-nopassword.xml");
public static final String USER_NOPASSWORD_USERNAME = "nopassword";
public static final File ROLE_WS_FILE = new File(COMMON_DIR, "role-ws.xml");
public static final File ROLE_READER_FILE = new File(COMMON_DIR, "role-reader.xml");
public static final File ROLE_ADDER_FILE = new File(COMMON_DIR, "role-adder.xml");
public static final File ROLE_MODIFIER_FILE = new File(COMMON_DIR, "role-modifier.xml");
public static final String ROLE_MODIFIER_OID = "82005ae4-d90b-11e4-bdcc-001e8c717e5b";
public static final File RESOURCE_OPENDJ_FILE = new File(COMMON_DIR, "resource-opendj.xml");
public static final String RESOURCE_OPENDJ_OID = "ef2bc95b-76e0-59e2-86d6-3d4f02d3ffff";
public static final String CONNECTOR_LDAP_TYPE = "com.evolveum.polygon.connector.ldap.LdapConnector";
protected static final Pattern PATTERN_AUDIT_EVENT_ID = Pattern.compile(".*\\seid=([^,]+),\\s.*");
protected static final Pattern PATTERN_AUDIT_SESSION_ID = Pattern.compile(".*\\ssid=([^,]+),\\s.*");
protected static final Pattern PATTERN_AUDIT_TASK_ID = Pattern.compile(".*\\stid=([^,]+),\\s.*");
public static final String NS_COMMON = ModelClientUtil.NS_COMMON;
public static final String NS_TYPES = ModelClientUtil.NS_TYPES;
public static final String NS_RI = ModelClientUtil.NS_RI;
public static final String NS_ICFS = ModelClientUtil.NS_ICFS;
protected static final QName TYPES_POLYSTRING_ORIG = new QName(NS_TYPES, "orig");
protected static final String CHANNEL_WS = "http://midpoint.evolveum.com/xml/ns/public/model/channels-3#webService";
public static final QName ATTR_ICF_NAME_NAME = new QName(NS_ICFS, "name");
protected static final QName COMMON_PATH = new QName(NS_COMMON, "path");
protected static final QName COMMON_VALUE = new QName(NS_COMMON, "value");
protected static DocumentBuilder domDocumentBuilder;
protected static ModelPortType modelPort;
protected static SystemConfigurationType configurationType;
private static final File DEFAULT_SERVER_LOG_FILE = new File("/opt/tomcat/logs/idm.log");
private static final String AUDIT_LOGGER_NAME = "com.evolveum.midpoint.audit.log";
private File serverLogFile = null;
@BeforeClass
public void beforeTests() throws Exception {
displayTestTitle("beforeTests");
startResources();
}
/**
* Takes care of system initialization. Need to be done before any tests are to be run.
* */
protected void startResources() throws Exception {
}
@AfterClass
public void afterTests() throws Exception {
displayTestTitle("afterTests");
modelPort = createModelPort();
cleanRepository();
stopResources();
LOGGER.info("WebService test suite finished.");
}
protected void stopResources() throws Exception {
}
protected static ModelPortType createModelPort() {
return createModelPort(USER_ADMINISTRATOR_USERNAME, USER_ADMINISTRATOR_PASSWORD);
}
protected static ModelPortType createModelPort(String username, String password) {
return createModelPort(username, password, WSConstants.PW_DIGEST);
}
/**
* Creates webservice client connecting to midpoint
* */
protected static ModelPortType createModelPort(String username, String password, String passwordType) {
String endpoint = ENDPOINT;
if (System.getProperty("midpoint.endpoint") != null) {
endpoint = System.getProperty("midpoint.endpoint");
}
LOGGER.info("Creating model client endpoint: {} , username={}, password={}",
new Object[] {endpoint, username, password});
ModelService modelService = new ModelService();
ModelPortType modelPort = modelService.getModelPort();
BindingProvider bp = (BindingProvider)modelPort;
Map<String, Object> requestContext = bp.getRequestContext();
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpoint);
org.apache.cxf.endpoint.Client client = ClientProxy.getClient(modelPort);
org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();
Map<String, Object> outProps = new HashMap<String, Object>();
if (username != null) {
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
outProps.put(WSHandlerConstants.USER, username);
outProps.put(WSHandlerConstants.PASSWORD_TYPE, passwordType);
ClientPasswordHandler.setPassword(password);
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordHandler.class.getName());
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
cxfEndpoint.getOutInterceptors().add(wssOut);
}
cxfEndpoint.getInInterceptors().add(new LoggingInInterceptor());
cxfEndpoint.getOutInterceptors().add(new LoggingOutInterceptor());
return modelPort;
}
/**
* Retrieves and returns actual system configuration
* */
protected SystemConfigurationType getConfiguration() throws FaultMessage {
return getObject(SystemConfigurationType.class, SystemObjectsType.SYSTEM_CONFIGURATION.value());
}
protected <O extends ObjectType> O getObject(Class<O> type, String oid) throws FaultMessage {
Holder<ObjectType> objectHolder = new Holder<ObjectType>();
Holder<OperationResultType> resultHolder = new Holder<OperationResultType>();
modelPort.getObject(getTypeQName(type), oid, null, objectHolder, resultHolder);
assertSuccess(resultHolder.value);
return (O) objectHolder.value;
}
private File getServerLogFile() {
if (serverLogFile == null) {
if (System.getProperty("midpoint.serverLogFile") != null) {
serverLogFile = new File(System.getProperty("midpoint.serverLogFile"));
} else {
serverLogFile = DEFAULT_SERVER_LOG_FILE;
}
}
return serverLogFile;
}
/**
* returns URI of type passed as argument
* */
protected static String getTypeUri(Class<? extends ObjectType> type){
return ModelClientUtil.getTypeUri(type);
}
protected static QName getTypeQName(Class<? extends ObjectType> type){
return ModelClientUtil.getTypeQName(type);
}
/**
* Returns documentBuilder instance - used to create documents and polystrings
* */
protected static Document getDocument(){
return DOMUtil.getDocument();
}
/**
* Creates polystring type with String value passed in argument
* */
protected static PolyStringType createPolyStringType(String string, Document doc) {
PolyStringType polyStringType = new PolyStringType();
Element origElement = createTextElement(TYPES_POLYSTRING_ORIG, string, doc);
polyStringType.getContent().add(origElement);
return polyStringType;
}
protected static Element createTextElement(QName qname, String value, Document doc) {
Element element = doc.createElementNS(qname.getNamespaceURI(), qname.getLocalPart());
element.setTextContent(value);
return element;
}
// /**
// * Creates CredentialsType - type used to store password. It's value is String password
// * representation passed via argument
// * */
// protected static CredentialsType createPasswordCredentials(String password) {
// CredentialsType credentialsType = new CredentialsType();
// credentialsType.setPassword(createPasswordType(password));
// return credentialsType;
// }
//
// protected static PasswordType createPasswordType(String password) {
// PasswordType passwordType = new PasswordType();
// passwordType.setValue(createProtectedString(password));
// return passwordType;
// }
//
// protected static ProtectedStringType createProtectedString(String clearValue) {
// ProtectedStringType protectedString = new ProtectedStringType();
// protectedString.setClearValue(clearValue);
// return protectedString;
// }
protected static Element createPathElement(String stringPath, Document doc) {
String pathDeclaration = "declare default namespace '" + NS_COMMON + "'; " + stringPath;
return createTextElement(COMMON_PATH, pathDeclaration, doc);
}
protected static <T> JAXBElement<T> toJaxbElement(QName name, T value){
return new JAXBElement<T>(name, (Class<T>) value.getClass(), value);
}
protected static Element parseElement(String stringXml) throws SAXException, IOException {
return DOMUtil.getFirstChildElement(DOMUtil.parseDocument(stringXml));
}
protected <O extends ObjectType> void deleteObject(Class<O> type, String oid) throws FaultMessage {
deleteObject(type, oid, null);
}
protected <O extends ObjectType> void deleteObject(Class<O> type, String oid, ModelExecuteOptionsType options) throws FaultMessage {
ObjectDeltaListType deltaList = new ObjectDeltaListType();
ObjectDeltaType delta = new ObjectDeltaType();
delta.setObjectType(getTypeQName(type));
delta.setChangeType(ChangeTypeType.DELETE);
delta.setOid(oid);
deltaList.getDelta().add(delta);
ObjectDeltaOperationListType deltaOpList = modelPort.executeChanges(deltaList, options);
assertSuccess(deltaOpList);
}
protected <O extends ObjectType> String addObject(O object) throws FaultMessage {
ObjectDeltaListType deltaList = new ObjectDeltaListType();
ObjectDeltaType delta = new ObjectDeltaType();
delta.setObjectType(getTypeQName(object.getClass()));
delta.setChangeType(ChangeTypeType.ADD);
delta.setObjectToAdd(object);
deltaList.getDelta().add(delta);
ObjectDeltaOperationListType deltaOpList = modelPort.executeChanges(deltaList, null);
assertSuccess(deltaOpList);
return deltaOpList.getDeltaOperation().get(0).getObjectDelta().getOid();
}
protected <O extends ObjectType> void assertObjectCount(Class<O> type, int expCount) throws FaultMessage {
assertEquals("Unexpected count of "+type.getSimpleName(), expCount, countObjects(type));
}
protected <O extends ObjectType> int countObjects(Class<O> type) throws FaultMessage {
Holder<OperationResultType> resultHolder = new Holder<OperationResultType>();
Holder<ObjectListType> objectListHolder = new Holder<ObjectListType>();
modelPort.searchObjects(getTypeQName(type), null, null, objectListHolder, resultHolder);
assertSuccess(resultHolder.value);
Integer count = objectListHolder.value.getCount();
if (count != null) {
assertEquals("Wrong count", (Integer)objectListHolder.value.getObject().size(), count);
}
return objectListHolder.value.getObject().size();
}
protected <F extends FocusType> String getSingleLinkOid(F focus) {
List<ObjectReferenceType> linkRefs = focus.getLinkRef();
assertEquals("Unexpected number of links for "+focus, 1, linkRefs.size());
return linkRefs.get(0).getOid();
}
protected void assertUser(UserType user, String expOid, String expName) {
assertEquals("Wrong user oid", expOid, user.getOid());
assertEquals("Wrong user name", expName, ModelClientUtil.getOrig(user.getName()));
}
protected void assertUser(UserType user, String expOid, String expName, String expGivenName, String expFamilyName) {
assertEquals("Wrong user oid", expOid, user.getOid());
assertEquals("Wrong user name", expName, ModelClientUtil.getOrig(user.getName()));
assertEquals("Wrong user givenName", expGivenName, ModelClientUtil.getOrig(user.getGivenName()));
assertEquals("Wrong user familyName", expFamilyName, ModelClientUtil.getOrig(user.getFamilyName()));
}
protected void assertSuccess(ObjectDeltaOperationListType deltaOpList) {
for (ObjectDeltaOperationType deltaOperation: deltaOpList.getDeltaOperation()) {
OperationResultType result = deltaOperation.getExecutionResult();
assertSuccess(result);
}
}
protected void assertSuccess(Holder<OperationResultType> resultHolder) {
assertSuccess(resultHolder.value);
}
protected void assertSuccess(OperationResultType result) {
assertEquals("Operation "+result.getOperation()+" failed:"+result.getStatus()+": " + result.getMessage(),
OperationResultStatusType.SUCCESS, result.getStatus());
// TODO: look inside
}
protected <F extends FaultType> void assertFaultMessage(FaultMessage fault, Class<F> expectedFaultInfoClass, String expectedMessage) {
FaultType faultInfo = fault.getFaultInfo();
assertNotNull("No fault info in "+fault);
if (expectedFaultInfoClass != null && !expectedFaultInfoClass.isAssignableFrom(faultInfo.getClass())) {
AssertJUnit.fail("Expected that faultInfo will be of type "+expectedFaultInfoClass+", but it was "+faultInfo.getClass());
}
if (expectedMessage != null) {
assertTrue("Wrong message in fault: "+fault.getMessage(), fault.getMessage().contains(expectedMessage));
assertTrue("Wrong message in fault info: "+faultInfo.getMessage(), faultInfo.getMessage().contains(expectedMessage));
}
OperationResultType result = faultInfo.getOperationResult();
assertNotNull("No result in faultInfo in "+fault, result);
assertEquals("Expected that resut in FaultInfo will be fatal error, but it was "+result.getStatus(),
OperationResultStatusType.FATAL_ERROR, result.getStatus());
}
protected void assertSoapSecurityFault(SOAPFaultException e, String expectedCode, String expectedMessage) {
// CXF by default replaces the real error with "safe" values
assertSoapFault(e, "SecurityError", "security error");
}
protected void assertSoapFault(SOAPFaultException e, String expectedCode, String expectedMessage) {
SOAPFault fault = e.getFault();
String faultCode = fault.getFaultCode();
display("SOAP fault code: "+faultCode);
assertTrue("Unexpected fault code: "+faultCode, faultCode.endsWith(expectedCode));
String message = e.getMessage();
assertTrue("Unexpected fault message: "+message, message.contains(expectedMessage));
}
protected void displayFault(FaultMessage fault) {
System.out.println("Got fault:");
fault.printStackTrace(System.out);
LOGGER.error("Got fault:\n{}",fault,fault);
}
protected void displayTestTitle(String testName) {
TestUtil.displayTestTile(testName);
}
protected void display(String msg) {
System.out.println(msg);
LOGGER.info("{}", msg);
}
protected <O extends ObjectType> void display(O object) throws JAXBException {
String xmlString = ModelClientUtil.marshallToSting(object);
System.out.println(xmlString);
LOGGER.info("{}", xmlString);
}
protected void display(OperationResultType result) throws JAXBException {
String xmlString = ModelClientUtil.marshallToSting(new QName(NS_COMMON,"result"), result, true);
System.out.println("Result:");
System.out.println(xmlString);
LOGGER.info("Result:\n{}", xmlString);
}
protected LogfileTestTailer createLogTailer() throws IOException {
return new LogfileTestTailer(getServerLogFile(), AUDIT_LOGGER_NAME, true);
}
private void checkAuditEnabled(SystemConfigurationType configurationType) throws FaultMessage {
LoggingConfigurationType loggingConfig = configurationType.getLogging();
AuditingConfigurationType auditConfig = loggingConfig.getAuditing();
if (auditConfig == null) {
auditConfig = new AuditingConfigurationType();
auditConfig.setEnabled(true);
loggingConfig.setAuditing(auditConfig);
} else {
if (BooleanUtils.isTrue(auditConfig.isEnabled())) {
return;
}
auditConfig.setEnabled(true);
}
ObjectDeltaListType deltaList = ModelClientUtil.createModificationDeltaList(SystemConfigurationType.class,
SystemObjectsType.SYSTEM_CONFIGURATION.value(), "logging", ModificationTypeType.REPLACE, loggingConfig);
ObjectDeltaOperationListType deltaOpList = modelPort.executeChanges(deltaList, null);
assertSuccess(deltaOpList);
}
protected void assertAuditLoginFailed(LogfileTestTailer tailer, String expectedMessage) {
tailer.assertAudit(1);
String auditMessage = tailer.getAuditMessages().get(0);
assertTrue("Audit: not login: "+auditMessage, auditMessage.contains("et=CREATE_SESSION"));
assertTrue("Audit: not failure: "+auditMessage, auditMessage.contains("o=FATAL_ERROR"));
assertTrue("Audit: wrong message: "+auditMessage, auditMessage.contains(expectedMessage));
}
protected void displayAudit(LogfileTestTailer tailer) {
display("Audit:");
for (String auditMessage: tailer.getAuditMessages()) {
display(auditMessage);
}
}
protected void assertAuditIds(LogfileTestTailer tailer) {
List<String> eids = new ArrayList<String>();
String sid = null;
String tid = null;
for (String auditMessage: tailer.getAuditMessages()) {
String msgEid = getAuditEid(auditMessage);
if (eids.contains(msgEid)) {
AssertJUnit.fail("Event ID "+msgEid+" is not unique: "+auditMessage);
}
String msgTid = getAuditTid(auditMessage);
if (msgTid == null) {
AssertJUnit.fail("Audit message without task ID: "+auditMessage);
}
if (tid == null) {
tid = msgTid;
} else {
assertEquals("Unmatched audit task ID: "+auditMessage, tid, msgTid);
}
String msgSid = getAuditSid(auditMessage);
if (msgSid != null) {
if (sid == null) {
sid = msgSid;
} else {
assertEquals("Unmatched audit session ID: "+auditMessage, sid, msgSid);
}
}
}
}
protected String getAuditEid(String auditMessage) {
return getAuditId(auditMessage, PATTERN_AUDIT_EVENT_ID);
}
protected String getAuditSid(String auditMessage) {
return getAuditId(auditMessage, PATTERN_AUDIT_SESSION_ID);
}
protected String getAuditTid(String auditMessage) {
return getAuditId(auditMessage, PATTERN_AUDIT_TASK_ID);
}
protected String getAuditId(String auditMessage, Pattern pattern) {
Matcher matcher = pattern.matcher(auditMessage);
if (!matcher.matches()) {
return null;
}
String match = matcher.group(1);
if (match == null || match.equals("null")) {
return null;
}
return match;
}
protected void assertAuditLoginLogout(LogfileTestTailer tailer) {
List<String> msgs = tailer.getAuditMessages();
String firstMsg = msgs.get(0);
assertTrue("Audit: first: not login: "+firstMsg, firstMsg.contains("et=CREATE_SESSION"));
assertTrue("Audit: first: not success: "+firstMsg, firstMsg.contains("o=SUCCESS"));
String lastMsg = msgs.get(msgs.size() - 1);
assertTrue("Audit: last: not logout: "+lastMsg, lastMsg.contains("et=TERMINATE_SESSION"));
assertTrue("Audit: last: not success: "+lastMsg, lastMsg.contains("o=SUCCESS"));
}
protected void assertAuditOperation(LogfileTestTailer tailer, String expectedEventType) {
assertAuditOperation(tailer, expectedEventType, OperationResultStatusType.SUCCESS, null);
}
protected void assertAuditOperation(LogfileTestTailer tailer, String expectedEventType,
OperationResultStatusType expectedStatus, String expectedMessage) {
List<String> msgs = tailer.getAuditMessages();
String reqMsg = msgs.get(1);
assertTrue("Audit: request: wrong operation: "+reqMsg, reqMsg.contains("et="+expectedEventType));
assertTrue("Audit: request: not request: "+reqMsg, reqMsg.contains("es=REQUEST"));
String execMsg = msgs.get(2);
assertTrue("Audit: exec: wrong operation: "+execMsg, execMsg.contains("et="+expectedEventType));
assertTrue("Audit: exec: not execution: "+execMsg, execMsg.contains("es=EXECUTION"));
assertTrue("Audit: exec: wrong status, expected '"+expectedStatus+"': "+execMsg, execMsg.contains("o="+expectedStatus));
if (expectedMessage != null) {
assertTrue("Audit: exec: wrong message, expected '"+expectedMessage+"': "+execMsg, execMsg.matches(".*m=.*"+expectedMessage+".*"));
}
}
protected <O extends ObjectType> void assertModifyMetadata(O object, String actorOid, XMLGregorianCalendar startTs, XMLGregorianCalendar endTs) {
MetadataType metadata = object.getMetadata();
assertEquals("Wrong metadata modifierRef in "+object, actorOid, metadata.getModifierRef().getOid());
assertEquals("Wrong metadata modify channel in "+object, CHANNEL_WS, metadata.getModifyChannel());
TestUtil.assertBetween("Wrong password modifyTimestamp in "+object, startTs, endTs, metadata.getModifyTimestamp());
}
protected <O extends ObjectType> void assertCreateMetadata(O object, String actorOid, XMLGregorianCalendar startTs, XMLGregorianCalendar endTs) {
MetadataType metadata = object.getMetadata();
assertEquals("Wrong metadata creatorRef in "+object, actorOid, metadata.getCreatorRef().getOid());
assertEquals("Wrong metadata create channel in "+object, CHANNEL_WS, metadata.getCreateChannel());
TestUtil.assertBetween("Wrong createTimestamp in "+object, startTs, endTs, metadata.getCreateTimestamp());
}
protected void assertPasswordModifyMetadata(UserType user, String actorOid, XMLGregorianCalendar startTs, XMLGregorianCalendar endTs) {
MetadataType passwordMetadata = user.getCredentials().getPassword().getMetadata();
assertEquals("Wrong password metadata modifierRef", actorOid, passwordMetadata.getModifierRef().getOid());
assertEquals("Wrong password metadata modify channel", CHANNEL_WS, passwordMetadata.getModifyChannel());
TestUtil.assertBetween("Wrong password modifyTimestamp", startTs, endTs, passwordMetadata.getModifyTimestamp());
}
protected void assertPasswordCreateMetadata(UserType user, String actorOid, XMLGregorianCalendar startTs, XMLGregorianCalendar endTs) {
MetadataType passwordMetadata = user.getCredentials().getPassword().getMetadata();
assertEquals("Wrong password metadata creatorRef", actorOid, passwordMetadata.getCreatorRef().getOid());
assertEquals("Wrong password metadata create channel", CHANNEL_WS, passwordMetadata.getCreateChannel());
TestUtil.assertBetween("Wrong password createTimestamp", startTs, endTs, passwordMetadata.getCreateTimestamp());
}
protected void assertAttribute(ShadowType shadow, String attrName, String attrVal) {
assertAttribute(shadow, new QName(NS_RI, attrName), attrVal);
}
protected void assertAttribute(ShadowType shadow, QName attrName, String attrVal) {
ShadowAttributesType attributes = shadow.getAttributes();
for (Object any: attributes.getAny()) {
if (any instanceof Element) {
Element element = (Element)any;
if (DOMUtil.getQName(element).equals(attrName)) {
assertEquals("Wrong attribute "+attrName+" in shadow "+ModelClientUtil.toString(shadow), attrVal, element.getTextContent());
}
} else if (any instanceof JAXBElement<?>) {
JAXBElement<?> jaxbElement = (JAXBElement<?>)any;
if (jaxbElement.getName().equals(attrName)) {
assertEquals("Wrong attribute "+attrName+" in shadow "+ModelClientUtil.toString(shadow), attrVal, jaxbElement.getValue().toString());
}
} else {
AssertJUnit.fail("Unexpected thing "+any+" in shadow attributes");
}
}
}
protected void assertNoAttribute(ShadowType shadow, String attrName) {
assertNoAttribute(shadow, new QName(NS_RI, attrName));
}
protected void assertNoAttribute(ShadowType shadow, QName attrName) {
ShadowAttributesType attributes = shadow.getAttributes();
for (Object any: attributes.getAny()) {
if (any instanceof Element) {
Element element = (Element)any;
if (DOMUtil.getQName(element).equals(attrName)) {
AssertJUnit.fail("Unexpected attribute "+attrName+" in shadow "+ModelClientUtil.toString(shadow)+": "+element.getTextContent());
}
} else if (any instanceof JAXBElement<?>) {
JAXBElement<?> jaxbElement = (JAXBElement<?>)any;
if (jaxbElement.getName().equals(attrName)) {
AssertJUnit.fail("Unexpected attribute "+attrName+" in shadow "+ModelClientUtil.toString(shadow)+": "+jaxbElement.getValue());
}
} else {
AssertJUnit.fail("Unexpected thing "+any+" in shadow attributes");
}
}
}
/**
* Clean the repository after tests. Preserves user administrator
* */
protected void cleanRepository() throws FaultMessage {
cleanObjects(UserType.class, false, SystemObjectsType.USER_ADMINISTRATOR.value());
cleanObjects(RoleType.class, false, SystemObjectsType.ROLE_SUPERUSER.value(), SystemObjectsType.ROLE_END_USER.value());
cleanObjects(ResourceType.class, false);
cleanObjects(ShadowType.class, true);
}
private <O extends ObjectType> void cleanObjects(Class<O> type, boolean raw, String... protectedOids) throws FaultMessage {
Holder<OperationResultType> resultHolder = new Holder<OperationResultType>();
Holder<ObjectListType> objectListHolder = new Holder<ObjectListType>();
SelectorQualifiedGetOptionsType rootOpts = null;
ModelExecuteOptionsType execOpts = null;
if (raw) {
rootOpts = ModelClientUtil.createRootGetOptions(ModelClientUtil.createRawGetOption());
execOpts = ModelClientUtil.createRawExecuteOption();
}
modelPort.searchObjects(getTypeQName(type), null, rootOpts, objectListHolder, resultHolder);
List<String> protectedOidList = Arrays.asList(protectedOids);
ObjectListType objectList = objectListHolder.value;
for (ObjectType object: objectList.getObject()) {
if (!protectedOidList.contains(object.getOid())) {
display("Deleting "+type.getSimpleName()+" "+ModelClientUtil.toString(object));
deleteObject(type, object.getOid(), execOpts);
}
}
}
@Test
public void test000SanityAndCleanup() throws Exception {
final String TEST_NAME = "test000SanityAndCleanup";
displayTestTitle(TEST_NAME);
modelPort = createModelPort();
configurationType = getConfiguration();
checkAuditEnabled(configurationType);
cleanRepository();
}
}