/**
 * OWASP Enterprise Security API (ESAPI)
 * 
 * This file is part of the Open Web Application Security Project (OWASP)
 * Enterprise Security API (ESAPI) project. For details, please see
 * <a href="http://www.owasp.org/index.php/ESAPI">http://www.owasp.org/index.php/ESAPI</a>.
 *
 * Copyright (c) 2007 - The OWASP Foundation
 * 
 * The ESAPI is published by OWASP under the BSD license. You should read and accept the
 * LICENSE before you use, modify, and/or redistribute this software.
 * 
 * @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect Security</a>
 * @created 2007
 */
package org.owasp.esapi.reference.crypto;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.util.Properties;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import org.owasp.esapi.errors.EncryptionException;

/**
 * The Class EncryptedPropertiesTest.
 * 
 * @author August Detlefsen (augustd at codemagi dot com)
 *         <a href="http://www.codemagi.com">CodeMagi, Inc.</a>
 * @since October 8, 2010
 */
public class EncryptedPropertiesUtilsTest extends TestCase {

	private static final String KEY1	= "quick";
	private static final String VALUE1	= "brown fox";
	private static final String KEY2	= "jumps";
	private static final String VALUE2	= "lazy dog";
	private static final String KEY3	= "joe bob";
	private static final String VALUE3	= "jim bob";
	private static final String KEY4	= "sally sue";
	private static final String VALUE4	= "betty mae";

	private static final String PLAINTEXT_FILENAME		= "plaintext.properties";
	private static final String ENCRYPTED_FILENAME_1	= "encrypted.properties";
	private static final String ENCRYPTED_FILENAME_2	= "encrypted.2.properties";

	/**
	 * Instantiates a new encrypted properties test.
	 * 
	 * @param testName
	 *            the test name
	 */
	public EncryptedPropertiesUtilsTest(String testName) {
		super(testName);
	}

	/**
	 * {@inheritDoc}
	 */
	protected void setUp() throws Exception {
		//write an initial plaintext properties file
		Properties props = new Properties();
		props.setProperty(KEY3, VALUE3);
		props.setProperty(KEY4, VALUE4);

		props.store(new FileOutputStream(PLAINTEXT_FILENAME), "Plaintext test file created by EncryptedPropertiesUtilsTest");
	}

	/**
	 * {@inheritDoc}
	 */
	protected void tearDown() throws Exception {
		File[] delFiles = new File[] { new File(PLAINTEXT_FILENAME), new File(ENCRYPTED_FILENAME_1), new File(ENCRYPTED_FILENAME_2) };
        for ( File f : delFiles ) {
            f.deleteOnExit();
        }
	}

	/**
	 * Suite.
	 * 
	 * @return the test
	 */
	public static Test suite() {
		TestSuite suite = new TestSuite(EncryptedPropertiesUtilsTest.class);

		return suite;
	}

	/**
	 * Test of creating and storing a new EncryptedProperties from scratch,
	 * as if calling:
	 * <code>
	 *     EncryptedPropertiesUtils --out encrypted.properties
	 * </code>
	 *
	 * @throws Exception Any exception that occurs
	 */
	public void testCreateNew() throws Exception {

		//create a new properties with no input
		Properties props = EncryptedPropertiesUtils.loadProperties(null, null);
		
		//add some properties
		Object prop1 = EncryptedPropertiesUtils.addProperty(props, KEY1, VALUE1);
		assertNull("Expected null but returned: " + prop1, prop1);

		Object prop2 = EncryptedPropertiesUtils.addProperty(props, KEY2, VALUE2);
		assertNull("Expected null but returned: " + prop2, prop2);

		//store the file 
		EncryptedPropertiesUtils.storeProperties(ENCRYPTED_FILENAME_1, props, "Encrypted Properties File generated by EncryptedPropertiesUtilsTest");

		//try reading in the resulting file
		ReferenceEncryptedProperties loadedProps = new ReferenceEncryptedProperties();
		loadedProps.load(new FileReader(ENCRYPTED_FILENAME_1));
		
		assertEquals(VALUE1, loadedProps.getProperty(KEY1));
		assertEquals(VALUE2, loadedProps.getProperty(KEY2));
	}

	/**
	 * Test of loading a plaintext file and storing it as an encrypted properties file,
	 * as if calling:
	 * <code>
	 *     EncryptedPropertiesUtils --in plaintext.properties --out encrypted.properties --in-encrypted false
	 * </code>
	 *
	 * @throws Exception Any exception that occurs
	 */
	public void testLoadPlaintextAndEncrypt() throws Exception {

		//load the plaintext properties file
		Properties props = EncryptedPropertiesUtils.loadProperties(PLAINTEXT_FILENAME, false);

		//test some properties using getProperty
		assertEquals(VALUE3, props.getProperty(KEY3));
		assertEquals(VALUE4, props.getProperty(KEY4));

		//store the file
		EncryptedPropertiesUtils.storeProperties(ENCRYPTED_FILENAME_1, props, "Encrypted Properties File generated by EncryptedPropertiesUtilsTest");

		//try reading in the resulting file
		ReferenceEncryptedProperties loadedProps = new ReferenceEncryptedProperties();
		loadedProps.load(new FileReader(ENCRYPTED_FILENAME_1));

		assertEquals(VALUE3, loadedProps.getProperty(KEY3));
		assertEquals(VALUE4, loadedProps.getProperty(KEY4));
	}

	/**
	 * Test of loading an encrypted file, adding new properties and storing it as an encrypted properties file,
	 * as if calling:
	 * <code>
	 *     EncryptedPropertiesUtils --in encrypted.properties --out encrypted.2.properties
	 * </code>
	 *
	 * @throws Exception Any exception that occurs
	 */
	public void testLoadEncryptedAndAdd() throws Exception {

		//load the plaintext properties file
		Properties props = EncryptedPropertiesUtils.loadProperties(ENCRYPTED_FILENAME_1, true);

		//test some properties
		assertEquals(VALUE3, props.getProperty(KEY3));
		assertEquals(VALUE4, props.getProperty(KEY4));

		//add some new properties
		EncryptedPropertiesUtils.addProperty(props, KEY1, VALUE1);
		EncryptedPropertiesUtils.addProperty(props, KEY2, VALUE2);

		//test the newly added properties
		assertEquals(VALUE1, props.getProperty(KEY1));
		assertEquals(VALUE2, props.getProperty(KEY2));

		//store the file
		EncryptedPropertiesUtils.storeProperties(ENCRYPTED_FILENAME_2, props, "Encrypted Properties File generated by EncryptedPropertiesUtilsTest");

		//try reading in the resulting file
		ReferenceEncryptedProperties loadedProps = new ReferenceEncryptedProperties();
		loadedProps.load(new FileReader(ENCRYPTED_FILENAME_2));

		//test the values read in
		assertEquals(VALUE1, loadedProps.getProperty(KEY1));
		assertEquals(VALUE2, loadedProps.getProperty(KEY2));
		assertEquals(VALUE3, loadedProps.getProperty(KEY3));
		assertEquals(VALUE4, loadedProps.getProperty(KEY4));
	}

}
