Package org.lilyproject.tools.tester

Source Code of org.lilyproject.tools.tester.TestFieldType

/*
* Copyright 2012 NGDATA nv
*
* 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 org.lilyproject.tools.tester;

import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.codehaus.jackson.JsonNode;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.lilyproject.bytes.api.ByteArray;
import org.lilyproject.repository.api.Blob;
import org.lilyproject.repository.api.FieldType;
import org.lilyproject.repository.api.HierarchyPath;
import org.lilyproject.repository.api.LRepository;
import org.lilyproject.repository.api.LTable;
import org.lilyproject.repository.api.Link;
import org.lilyproject.repository.api.QName;
import org.lilyproject.repository.api.Record;
import org.lilyproject.repository.api.RecordException;
import org.lilyproject.repository.api.ValueType;
import org.lilyproject.testclientfw.Words;
import org.lilyproject.util.json.JsonUtil;

public class TestFieldType {
    private static final Random random = new Random();
    private final LTable table;
    private final LRepository repository;

    FieldType fieldType;
    private String linkedRecordTypeName;
    private String linkedRecordSource;
    private final JsonNode properties;

    public TestFieldType(FieldType fieldType, LTable table, LRepository repository, JsonNode properties) {
        this.fieldType = fieldType;
        this.table = table;
        this.repository = repository;
        this.properties = properties;
        if (properties != null) {
            this.linkedRecordTypeName = JsonUtil.getString(properties, "recordType", null);
            this.linkedRecordSource = JsonUtil.getString(properties, "recordSource", null);
        }
    }

    public FieldType getFieldType() {
        return fieldType;
    }

    public String getLinkedRecordTypeName(){
        return linkedRecordTypeName;
    }

    public String getLinkedRecordSource() {
        return linkedRecordSource;
    }

    public ActionResult generateValue(TestAction testAction) {
        return generateValue(testAction, fieldType.getValueType());
    }

    private ActionResult generateList(TestAction testAction, ValueType valueType) {
        int size = (int)Math.ceil(Math.random() * 2);
        List<Object> values = new ArrayList<Object>();
        long duration = 0;
        for (int i = 0; i < size; i++) {
            ActionResult result = generateValue(testAction, valueType);
            duration += result.duration;
            if (result.success) {
                values.add(result.object);
            } else {
                return new ActionResult(false, null, duration);
            }
        }
        return new ActionResult(true, values, duration);
    }

    private ActionResult generatePath(TestAction testAction, ValueType valueType) {
            int size = (int)Math.ceil(Math.random() * 3);
            Object[] elements = new Object[size];
            long duration = 0;
            for (int i = 0; i < size; i++) {
                ActionResult result = generateValue(testAction, valueType);
                duration += result.duration;
                if (result.success) {
                    elements[i] = result.object;
                } else {
                    return new ActionResult(false, null, duration);
                }
            }
            return new ActionResult(true, new HierarchyPath(elements), duration);
    }

    private ActionResult generateValue(TestAction testAction, ValueType valueType) {
        String name = valueType.getBaseName();

        if (name.equals("LIST")) {
            return generateList(testAction, valueType.getNestedValueType());
        } else if (name.equals("PATH")) {
            return generatePath(testAction, valueType.getNestedValueType());
        } else if (name.equals("STRING")) {
            return new ActionResult(true, generateString(), 0);
        } else if (name.equals("INTEGER")) {
            return new ActionResult(true, generateInt(), 0);
        } else if (name.equals("LONG")) {
            return new ActionResult(true, generateLong(), 0);
        } else if (name.equals("DOUBLE")) {
            return new ActionResult(true, generateDouble(), 0);
        } else if (name.equals("BOOLEAN")) {
            return new ActionResult(true, generateBoolean(), 0);
        } else if (name.equals("DATE")) {
            return new ActionResult(true, generateLocalDate(), 0);
        } else if (name.equals("DATETIME")) {
            return new ActionResult(true, generateDateTime(), 0);
        } else if (name.equals("BLOB")) {
            return new ActionResult(true, generateBlob(), 0);
        } else if (name.equals("BYTEARRAY")) {
            return new ActionResult(true, generateByteArray(), 0);
        } else if (name.equals("LINK")) {
                return testAction.linkFieldAction(this, null);
        } else if (name.equals("RECORD")) {
            try {
                return new ActionResult(true, generateRecord(testAction, valueType), 0);
            } catch (RecordException e) {
                throw new RuntimeException("Error generating record value (CFT)", e);
            }
        } else {
            throw new RuntimeException("Unsupported value type: " + name);
        }
    }

    private String generateString() {
        String value = null;
        // Default
        if (properties == null) {
            value = Words.get(Words.WordList.BIG_LIST, (int)Math.floor(Math.random() * 100));
        } else {
            int wordCount = JsonUtil.getInt(properties, "wordCount", 1);
            String wordString = JsonUtil.getString(properties, "enum", null);
            if (wordString != null) {
                String[] words = wordString.split(",");
                StringBuilder stringBuilder = new StringBuilder(20 * wordCount);
                for (int i = 0; i < wordCount; i++) {
                    if (i > 0) {
                        stringBuilder.append(' ');
                    }
                    int index = (int) (Math.random() * words.length);
                    stringBuilder.append(words[index]);
                }
                value = stringBuilder.toString();
            } else {
                value = Words.get(Words.WordList.BIG_LIST,wordCount);
            }
        }
        return value;
    }

    private ByteArray generateByteArray() {
        ByteArray value = null;
        // Default
        if (properties == null) {
            byte[] bytes = new byte[random.nextInt(100)];
            random.nextBytes(bytes);
            value = new ByteArray(bytes);
        } else {
            int length = JsonUtil.getInt(properties, "length", 100);
            byte[] bytes = new byte[length];
            random.nextBytes(bytes);
            value = new ByteArray(bytes);
        }
        return value;
    }

    private int generateInt() {
        // Default
        int value = 0;
        if (properties == null) {
            value = random.nextInt();
        } else {
            String numberString = JsonUtil.getString(properties, "enum", null);
            if (numberString != null) {
                String[] numbers = numberString.split(",");
                int index = (int) (Math.random() * numbers.length);
                value = Integer.valueOf(numbers[index]);
            } else {
                int min = JsonUtil.getInt(properties, "min", Integer.MIN_VALUE);
                int max = JsonUtil.getInt(properties, "max", Integer.MAX_VALUE);
                value = min + (int)(Math.random() * ((max - min) + 1));
            }
        }
        return value;
    }

    private long generateLong() {
        // Default
        long value = 0;
        if (properties == null) {
            value = random.nextLong();
        } else {
            String numberString = JsonUtil.getString(properties, "enum", null);
            if (numberString != null) {
                String[] numbers = numberString.split(",");
                int index = (int) (Math.random() * numbers.length);
                value = Long.valueOf(numbers[index]);
            } else {
                long min = JsonUtil.getLong(properties, "min", Long.MIN_VALUE);
                long max = JsonUtil.getLong(properties, "max", Long.MAX_VALUE);
                value = min + (long)(Math.random() * ((max - min) + 1));
            }
        }
        return value;
    }

    private double generateDouble() {
        // Default
        double value = 0;
        if (properties == null) {
            value = random.nextDouble();
        } else {
            String numberString = JsonUtil.getString(properties, "enum", null);
            if (numberString != null) {
                String[] numbers = numberString.split(",");
                int index = (int) (Math.random() * numbers.length);
                value = Double.valueOf(numbers[index]);
            } else {
                double min = JsonUtil.getDouble(properties, "min", Double.MIN_VALUE);
                double max = JsonUtil.getDouble(properties, "max", Double.MAX_VALUE);
                value = min + (double)(Math.random() * ((max - min) + 1));
            }
        }
        return value;
    }

    private Record generateRecord(TestAction testAction, ValueType valueType) throws RecordException {
        String valueTypeName = valueType.getName();
        String recordTypeName = valueTypeName.substring(valueTypeName.indexOf("<") + 1, valueTypeName.length()-1);
        TestActionContext context = testAction.getContext();
        TestRecordType testRecordType = context.recordTypes.get(QName.fromString(recordTypeName));
        Record record = context.repository.getRecordFactory().newRecord();
        record.setRecordType(testRecordType.getRecordType().getName());
        List<TestFieldType> testFieldTypes = testRecordType.getFieldTypes();
        for (TestFieldType testFieldType : testFieldTypes) {
            ActionResult actionResult = testFieldType.generateValue(testAction);
            record.setField(testFieldType.getFieldType().getName(), actionResult.object);

        }
        return record;
    }

    private boolean generateBoolean() {
        return random.nextBoolean();
    }

    private LocalDate generateLocalDate() {
        int year = 1950 + (int)(Math.random() * 100);
        int month = (int)Math.ceil(Math.random() * 12);
        int day = (int)Math.ceil(Math.random() * 25);
        return new LocalDate(year, month, day);
    }

    private DateTime generateDateTime() {
        int fail = 0;
        while (true) {
            int year = 1950 + (int)(Math.random() * 100);
            int month = (int)Math.ceil(Math.random() * 12);
            int day = (int)Math.ceil(Math.random() * 25);
            int hour = (int)Math.floor(Math.random() * 24);
            int minute = (int)Math.floor(Math.random() * 60);
            int second = (int)Math.floor(Math.random() * 60);
            try {
                return new DateTime(year, month, day, hour, minute, second, 0);
            } catch (IllegalArgumentException e) {
                // We can get exceptions here of the kind:
                //  "Illegal instant due to time zone offset transition"
                // This can occur if we happen to generate a time which falls in daylight
                // saving.
                if (fail > 10) {
                    throw new RuntimeException("Strange: did not succeed to generate a valid date after "
                            + fail + " tries.", e);
                }
                fail++;
            }
        }
    }

    private Blob generateBlob() {
        // Generate a blob that should be cleaned up by BlobIncubator
        actualGenerateBlob();
        return actualGenerateBlob();
    }

    private Blob actualGenerateBlob() {

        //4K, 150K, 200MB
        int[] sizes = new int[]{
                4000, 150000, 200000000
        };
//        long start = System.currentTimeMillis();
        int min = 1;
        int max = sizes[0 + (int)(Math.random() * ((2 - 0) + 1))];
        int size = min + (int)(Math.random() * ((max - min) + 1));
        byte[] bytes = new byte[size];
        random.nextBytes(bytes);
        Blob blob = new Blob("tester", (long)bytes.length, "test"+size);
        try {
            OutputStream outputStream = table.getOutputStream(blob);
            outputStream.write(bytes);
            outputStream.close();
//            System.out.println("created blob of size "+size+" in "+ (System.currentTimeMillis()-start) +" ms");
            return blob;
        } catch (Exception e) {
            throw new RuntimeException("Failed to generate blob", e);
        }

    }

    public Link generateLink() {
        return new Link(repository.getIdGenerator().newRecordId());
    }

    public ActionResult updateValue(TestAction testAction, Record record) {
        if (linkedRecordTypeName == null && linkedRecordSource == null)  {
            return generateValue(null); // The value will not be a link field, so we can give null here
        } else {
            Object value = record.getField(fieldType.getName());
            return updateLinkValue(testAction, value, fieldType.getValueType());
        }
    }

    private ActionResult updateLinkValue(TestAction testAction, Object value, ValueType valueType) {
        if (valueType.getBaseName().equals("LIST")) {
            List<Object> values = (List<Object>) value;
            int index = (int) (Math.random() * values.size());
            ActionResult result = updateLinkValue(testAction, values.get(index), valueType.getNestedValueType());
            if (result.success && result.object != null) {
                values.add(index, result.object);
                return new ActionResult(true, values, result.duration);
            }
            return result;
        } else if (valueType.getBaseName().equals("PATH")) {
            HierarchyPath path = (HierarchyPath) value;
            Object[] values = path.getElements();
            int index = (int) (Math.random() * values.length);
            // LinkedRecordTypeName should only be given in case of link fields
            ActionResult result = updateLinkValue(testAction, values[index], valueType.getNestedValueType());
            if (result.success && result.object != null) {
                values[index] = result.object;
                return new ActionResult(true, values, result.duration);
            }
            return result;
        } else {
            return updateLink(testAction, (Link) value);
        }
    }

    private ActionResult updateLink(TestAction testAction, Link link) {
        return testAction.linkFieldAction(this, link.getMasterRecordId());
    }
}
TOP

Related Classes of org.lilyproject.tools.tester.TestFieldType

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.