<commit_before>/*
 * 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.
 */

/*
 * Copyright 2015 Cloudius Systems
 *
 * Modified by Cloudius Systems
 */

#ifndef CQL3_SETS_HH
#define CQL3_SETS_HH

#include "cql3/abstract_marker.hh"
#include "maps.hh"
#include "column_specification.hh"
#include "column_identifier.hh"
#include "to_string.hh"
#include <unordered_set>

namespace cql3 {

#if 0
package org.apache.cassandra.cql3;

import java.nio.ByteBuffer;
import java.util.*;

import com.google.common.base.Joiner;

import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.db.composites.Composite;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.MapType;
import org.apache.cassandra.db.marshal.SetType;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.serializers.CollectionSerializer;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.transport.Server;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
#endif

/**
 * Static helper methods and classes for sets.
 */
class sets {
    sets() = delete;
public:
    static shared_ptr<column_specification> value_spec_of(shared_ptr<column_specification> column) {
        return make_shared<column_specification>(column->ks_name, column->cf_name,
                ::make_shared<column_identifier>(sprint("value(%s)", *column->name), true),
                dynamic_pointer_cast<set_type_impl>(column->type)->get_elements_type());
    }

    class literal : public term::raw {
        std::vector<shared_ptr<term::raw>> _elements;
    public:
        explicit literal(std::vector<shared_ptr<term::raw>> elements)
                : _elements(std::move(elements)) {
        }

        shared_ptr<term> prepare(const sstring& keyspace, shared_ptr<column_specification> receiver) {
            validate_assignable_to(keyspace, receiver);

            // We've parsed empty maps as a set literal to break the ambiguity so
            // handle that case now
            if (_elements.empty() && dynamic_pointer_cast<map_type_impl>(receiver->type)) {
                // use empty_type for comparator, set is empty anyway.
                std::map<bytes, bytes, serialized_compare> m(empty_type->as_less_comparator());
                return ::make_shared<maps::value>(std::move(m));
            }

            auto value_spec = value_spec_of(receiver);
            std::vector<shared_ptr<term>> values;
            values.reserve(_elements.size());
            bool all_terminal = true;
            for (shared_ptr<term::raw> rt : _elements)
            {
                auto t = rt->prepare(keyspace, value_spec);

                if (t->contains_bind_marker()) {
                    throw exceptions::invalid_request_exception(sprint("Invalid set literal for %s: bind variables are not supported inside collection literals", *receiver->name));
                }

                if (dynamic_pointer_cast<non_terminal>(t)) {
                    all_terminal = false;
                }

                values.push_back(std::move(t));
            }
            auto compare = dynamic_pointer_cast<set_type_impl>(receiver->type)->get_elements_type()->as_less_comparator();

            auto value = ::make_shared<delayed_value>(compare, std::move(values));
            if (all_terminal) {
                return value->bind(query_options::DEFAULT);
            } else {
                return value;
            }
        }

        void validate_assignable_to(const sstring& keyspace, shared_ptr<column_specification> receiver) {
            if (!dynamic_pointer_cast<set_type_impl>(receiver->type)) {
                // We've parsed empty maps as a set literal to break the ambiguity so
                // handle that case now
                if (dynamic_pointer_cast<map_type_impl>(receiver->type) && _elements.empty()) {
                    return;
                }

                throw exceptions::invalid_request_exception(sprint("Invalid set literal for %s of type %s", *receiver->name, *receiver->type->as_cql3_type()));
            }

            auto&& value_spec = value_spec_of(receiver);
            for (shared_ptr<term::raw> rt : _elements) {
                if (!is_assignable(rt->test_assignment(keyspace, value_spec))) {
                    throw exceptions::invalid_request_exception(sprint("Invalid set literal for %s: value %s is not of type %s", *receiver->name, *rt, *value_spec->type->as_cql3_type()));
                }
            }
        }

        assignment_testable::test_result
        test_assignment(const sstring& keyspace, shared_ptr<column_specification> receiver) {
            if (!dynamic_pointer_cast<set_type_impl>(receiver->type)) {
                // We've parsed empty maps as a set literal to break the ambiguity so handle that case now
                if (dynamic_pointer_cast<map_type_impl>(receiver->type) && _elements.empty()) {
                    return assignment_testable::test_result::WEAKLY_ASSIGNABLE;
                }

                return assignment_testable::test_result::NOT_ASSIGNABLE;
            }

            // If there is no elements, we can't say it's an exact match (an empty set if fundamentally polymorphic).
            if (_elements.empty()) {
                return assignment_testable::test_result::WEAKLY_ASSIGNABLE;
            }

            auto&& value_spec = value_spec_of(receiver);
            // FIXME: make assignment_testable::test_all() accept ranges
            std::vector<shared_ptr<assignment_testable>> to_test(_elements.begin(), _elements.end());
            return assignment_testable::test_all(keyspace, value_spec, to_test);
        }

        virtual sstring to_string() override {
            return "{" + join(", ", _elements) + "}";
        }
    };

    class value : public terminal, collection_terminal {
    public:
        std::set<bytes, serialized_compare> _elements;
    public:
        value(std::set<bytes, serialized_compare> elements)
                : _elements(std::move(elements)) {
        }

        static value from_serialized(bytes_view v, set_type type, int version) {
            try {
                // Collections have this small hack that validate cannot be called on a serialized object,
                // but compose does the validation (so we're fine).
                // FIXME: deserializeForNativeProtocol?!
                auto s = boost::any_cast<set_type_impl::native_type>(type->deserialize(v, version));
                std::set<bytes, serialized_compare> elements(type->as_less_comparator());
                for (auto&& element : s) {
                    elements.insert(elements.end(), type->get_elements_type()->decompose(element));
                }
                return value(std::move(elements));
            } catch (marshal_exception& e) {
                throw exceptions::invalid_request_exception(e.why());
            }
        }

        virtual bytes_opt get(const query_options& options) override {
            return get_with_protocol_version(options.get_protocol_version());
        }

        virtual bytes get_with_protocol_version(int protocol_version) override {
            return collection_type_impl::pack(_elements.begin(), _elements.end(),
                    _elements.size(), protocol_version);
        }

        bool equals(set_type st, const value& v) {
            if (_elements.size() != v._elements.size()) {
                return false;
            }
            auto&& elements_type = st->get_elements_type();
            return std::equal(_elements.begin(), _elements.end(),
                    v._elements.begin(),
                    [elements_type] (bytes_view v1, bytes_view v2) {
                        return elements_type->equal(v1, v2);
                    });
        }

        virtual sstring to_string() const override {
            sstring result = "{";
            bool first = true;
            for (auto&& e : _elements) {
                if (!first) {
                    result += ", ";
                }
                first = true;
                result += to_hex(e);
            }
            result += "}";
            return result;
        }
    };

    // See Lists.DelayedValue
    class delayed_value : public non_terminal {
        serialized_compare _comparator;
        std::vector<shared_ptr<term>> _elements;
    public:
        delayed_value(serialized_compare comparator, std::vector<shared_ptr<term>> elements)
            : _comparator(std::move(comparator)), _elements(std::move(elements)) {
        }

        virtual bool contains_bind_marker() const override {
            // False since we don't support them in collection
            return false;
        }

        virtual void collect_marker_specification(shared_ptr<variable_specifications> bound_names) override {
        }

        virtual shared_ptr<terminal> bind(const query_options& options) {
            std::set<bytes, serialized_compare> buffers(_comparator);
            for (auto&& t : _elements) {
                bytes_opt b = t->bind_and_get(options);

                if (!b) {
                    throw exceptions::invalid_request_exception("null is not supported inside collections");
                }

                // We don't support value > 64K because the serialization format encode the length as an unsigned short.
                if (b->size() > std::numeric_limits<uint16_t>::max()) {
                    throw exceptions::invalid_request_exception(sprint("Set value is too long. Set values are limited to %d bytes but %d bytes value provided",
                            std::numeric_limits<uint16_t>::max(),
                            b->size()));
                }

                buffers.insert(buffers.end(), std::move(*b));
            }
            return ::make_shared<value>(std::move(buffers));
        }
    };

    class marker : public abstract_marker {
    public:
        marker(int32_t bind_index, ::shared_ptr<column_specification> receiver)
            : abstract_marker{bind_index, std::move(receiver)}
        { }
#if 0
        protected Marker(int bindIndex, ColumnSpecification receiver)
        {
            super(bindIndex, receiver);
            assert receiver.type instanceof SetType;
        }
#endif

        virtual ::shared_ptr<terminal> bind(const query_options& options) override {
            throw std::runtime_error("");
        }
#if 0
        public Value bind(QueryOptions options) throws InvalidRequestException
        {
            ByteBuffer value = options.getValues().get(bindIndex);
            return value == null ? null : Value.fromSerialized(value, (SetType)receiver.type, options.getProtocolVersion());
        }
#endif
    };

#if 0
    public static class Setter extends Operation
    {
        public Setter(ColumnDefinition column, Term t)
        {
            super(column, t);
        }

        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
        {
            if (column.type.isMultiCell())
            {
                // delete + add
                CellName name = cf.getComparator().create(prefix, column);
                cf.addAtom(params.makeTombstoneForOverwrite(name.slice()));
            }
            Adder.doAdd(t, cf, prefix, column, params);
        }
    }

#endif
    class adder : public operation {
    public:
        adder(column_definition& column, shared_ptr<term> t)
            : operation(column, std::move(t)) {
        }

        virtual void execute(mutation& m, const clustering_prefix& row_key, const update_parameters& params) override {
            assert(column.type->is_multi_cell()); // "Attempted to add items to a frozen set";
            do_add(m, row_key, params, _t, column);
        }

        static void do_add(mutation& m, const clustering_prefix& row_key, const update_parameters& params,
                shared_ptr<term> t, const column_definition& column) {
            auto&& value = t->bind(params._options);
            auto set_value = dynamic_pointer_cast<sets::value>(std::move(value));
            auto set_type = dynamic_pointer_cast<set_type_impl>(column.type);
            if (column.type->is_multi_cell()) {
                if (!set_value || set_value->_elements.empty()) {
                    return;
                }

                // FIXME: mutation_view? not compatible with params.make_cell().
                collection_type_impl::mutation mut;
                for (auto&& e : set_value->_elements) {
                    mut.emplace_back(e, params.make_cell({}));
                }
                auto smut = set_type->serialize_mutation_form(mut);

                m.set_cell(row_key, column, std::move(smut));
            } else {
                // for frozen sets, we're overwriting the whole cell
                auto v = set_type->serialize_partially_deserialized_form(
                        {set_value->_elements.begin(), set_value->_elements.end()}, 3);
                if (set_value->_elements.empty()) {
                    m.set_cell(row_key, column, params.make_dead_cell());
                } else {
                    m.set_cell(row_key, column, params.make_cell(std::move(v)));
                }
            }
        }
    };

#if 0
    // Note that this is reused for Map subtraction too (we subtract a set from a map)
    public static class Discarder extends Operation
    {
        public Discarder(ColumnDefinition column, Term t)
        {
            super(column, t);
        }

        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
        {
            assert column.type.isMultiCell() : "Attempted to remove items from a frozen set";

            Term.Terminal value = t.bind(params.options);
            if (value == null)
                return;

            // This can be either a set or a single element
            Set<ByteBuffer> toDiscard = value instanceof Constants.Value
                                      ? Collections.singleton(((Constants.Value)value).bytes)
                                      : ((Sets.Value)value).elements;

            for (ByteBuffer bb : toDiscard)
            {
                cf.addColumn(params.makeTombstone(cf.getComparator().create(prefix, column, bb)));
            }
        }
    }
#endif
};

}

#endif
<commit_msg>cql: convert sets::setter to C++<commit_after>/*
 * 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.
 */

/*
 * Copyright 2015 Cloudius Systems
 *
 * Modified by Cloudius Systems
 */

#ifndef CQL3_SETS_HH
#define CQL3_SETS_HH

#include "cql3/abstract_marker.hh"
#include "maps.hh"
#include "column_specification.hh"
#include "column_identifier.hh"
#include "to_string.hh"
#include <unordered_set>

namespace cql3 {

#if 0
package org.apache.cassandra.cql3;

import java.nio.ByteBuffer;
import java.util.*;

import com.google.common.base.Joiner;

import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.composites.CellName;
import org.apache.cassandra.db.composites.Composite;
import org.apache.cassandra.db.marshal.AbstractType;
import org.apache.cassandra.db.marshal.MapType;
import org.apache.cassandra.db.marshal.SetType;
import org.apache.cassandra.exceptions.InvalidRequestException;
import org.apache.cassandra.serializers.CollectionSerializer;
import org.apache.cassandra.serializers.MarshalException;
import org.apache.cassandra.transport.Server;
import org.apache.cassandra.utils.ByteBufferUtil;
import org.apache.cassandra.utils.FBUtilities;
#endif

/**
 * Static helper methods and classes for sets.
 */
class sets {
    sets() = delete;
public:
    static shared_ptr<column_specification> value_spec_of(shared_ptr<column_specification> column) {
        return make_shared<column_specification>(column->ks_name, column->cf_name,
                ::make_shared<column_identifier>(sprint("value(%s)", *column->name), true),
                dynamic_pointer_cast<set_type_impl>(column->type)->get_elements_type());
    }

    class literal : public term::raw {
        std::vector<shared_ptr<term::raw>> _elements;
    public:
        explicit literal(std::vector<shared_ptr<term::raw>> elements)
                : _elements(std::move(elements)) {
        }

        shared_ptr<term> prepare(const sstring& keyspace, shared_ptr<column_specification> receiver) {
            validate_assignable_to(keyspace, receiver);

            // We've parsed empty maps as a set literal to break the ambiguity so
            // handle that case now
            if (_elements.empty() && dynamic_pointer_cast<map_type_impl>(receiver->type)) {
                // use empty_type for comparator, set is empty anyway.
                std::map<bytes, bytes, serialized_compare> m(empty_type->as_less_comparator());
                return ::make_shared<maps::value>(std::move(m));
            }

            auto value_spec = value_spec_of(receiver);
            std::vector<shared_ptr<term>> values;
            values.reserve(_elements.size());
            bool all_terminal = true;
            for (shared_ptr<term::raw> rt : _elements)
            {
                auto t = rt->prepare(keyspace, value_spec);

                if (t->contains_bind_marker()) {
                    throw exceptions::invalid_request_exception(sprint("Invalid set literal for %s: bind variables are not supported inside collection literals", *receiver->name));
                }

                if (dynamic_pointer_cast<non_terminal>(t)) {
                    all_terminal = false;
                }

                values.push_back(std::move(t));
            }
            auto compare = dynamic_pointer_cast<set_type_impl>(receiver->type)->get_elements_type()->as_less_comparator();

            auto value = ::make_shared<delayed_value>(compare, std::move(values));
            if (all_terminal) {
                return value->bind(query_options::DEFAULT);
            } else {
                return value;
            }
        }

        void validate_assignable_to(const sstring& keyspace, shared_ptr<column_specification> receiver) {
            if (!dynamic_pointer_cast<set_type_impl>(receiver->type)) {
                // We've parsed empty maps as a set literal to break the ambiguity so
                // handle that case now
                if (dynamic_pointer_cast<map_type_impl>(receiver->type) && _elements.empty()) {
                    return;
                }

                throw exceptions::invalid_request_exception(sprint("Invalid set literal for %s of type %s", *receiver->name, *receiver->type->as_cql3_type()));
            }

            auto&& value_spec = value_spec_of(receiver);
            for (shared_ptr<term::raw> rt : _elements) {
                if (!is_assignable(rt->test_assignment(keyspace, value_spec))) {
                    throw exceptions::invalid_request_exception(sprint("Invalid set literal for %s: value %s is not of type %s", *receiver->name, *rt, *value_spec->type->as_cql3_type()));
                }
            }
        }

        assignment_testable::test_result
        test_assignment(const sstring& keyspace, shared_ptr<column_specification> receiver) {
            if (!dynamic_pointer_cast<set_type_impl>(receiver->type)) {
                // We've parsed empty maps as a set literal to break the ambiguity so handle that case now
                if (dynamic_pointer_cast<map_type_impl>(receiver->type) && _elements.empty()) {
                    return assignment_testable::test_result::WEAKLY_ASSIGNABLE;
                }

                return assignment_testable::test_result::NOT_ASSIGNABLE;
            }

            // If there is no elements, we can't say it's an exact match (an empty set if fundamentally polymorphic).
            if (_elements.empty()) {
                return assignment_testable::test_result::WEAKLY_ASSIGNABLE;
            }

            auto&& value_spec = value_spec_of(receiver);
            // FIXME: make assignment_testable::test_all() accept ranges
            std::vector<shared_ptr<assignment_testable>> to_test(_elements.begin(), _elements.end());
            return assignment_testable::test_all(keyspace, value_spec, to_test);
        }

        virtual sstring to_string() override {
            return "{" + join(", ", _elements) + "}";
        }
    };

    class value : public terminal, collection_terminal {
    public:
        std::set<bytes, serialized_compare> _elements;
    public:
        value(std::set<bytes, serialized_compare> elements)
                : _elements(std::move(elements)) {
        }

        static value from_serialized(bytes_view v, set_type type, int version) {
            try {
                // Collections have this small hack that validate cannot be called on a serialized object,
                // but compose does the validation (so we're fine).
                // FIXME: deserializeForNativeProtocol?!
                auto s = boost::any_cast<set_type_impl::native_type>(type->deserialize(v, version));
                std::set<bytes, serialized_compare> elements(type->as_less_comparator());
                for (auto&& element : s) {
                    elements.insert(elements.end(), type->get_elements_type()->decompose(element));
                }
                return value(std::move(elements));
            } catch (marshal_exception& e) {
                throw exceptions::invalid_request_exception(e.why());
            }
        }

        virtual bytes_opt get(const query_options& options) override {
            return get_with_protocol_version(options.get_protocol_version());
        }

        virtual bytes get_with_protocol_version(int protocol_version) override {
            return collection_type_impl::pack(_elements.begin(), _elements.end(),
                    _elements.size(), protocol_version);
        }

        bool equals(set_type st, const value& v) {
            if (_elements.size() != v._elements.size()) {
                return false;
            }
            auto&& elements_type = st->get_elements_type();
            return std::equal(_elements.begin(), _elements.end(),
                    v._elements.begin(),
                    [elements_type] (bytes_view v1, bytes_view v2) {
                        return elements_type->equal(v1, v2);
                    });
        }

        virtual sstring to_string() const override {
            sstring result = "{";
            bool first = true;
            for (auto&& e : _elements) {
                if (!first) {
                    result += ", ";
                }
                first = true;
                result += to_hex(e);
            }
            result += "}";
            return result;
        }
    };

    // See Lists.DelayedValue
    class delayed_value : public non_terminal {
        serialized_compare _comparator;
        std::vector<shared_ptr<term>> _elements;
    public:
        delayed_value(serialized_compare comparator, std::vector<shared_ptr<term>> elements)
            : _comparator(std::move(comparator)), _elements(std::move(elements)) {
        }

        virtual bool contains_bind_marker() const override {
            // False since we don't support them in collection
            return false;
        }

        virtual void collect_marker_specification(shared_ptr<variable_specifications> bound_names) override {
        }

        virtual shared_ptr<terminal> bind(const query_options& options) {
            std::set<bytes, serialized_compare> buffers(_comparator);
            for (auto&& t : _elements) {
                bytes_opt b = t->bind_and_get(options);

                if (!b) {
                    throw exceptions::invalid_request_exception("null is not supported inside collections");
                }

                // We don't support value > 64K because the serialization format encode the length as an unsigned short.
                if (b->size() > std::numeric_limits<uint16_t>::max()) {
                    throw exceptions::invalid_request_exception(sprint("Set value is too long. Set values are limited to %d bytes but %d bytes value provided",
                            std::numeric_limits<uint16_t>::max(),
                            b->size()));
                }

                buffers.insert(buffers.end(), std::move(*b));
            }
            return ::make_shared<value>(std::move(buffers));
        }
    };

    class marker : public abstract_marker {
    public:
        marker(int32_t bind_index, ::shared_ptr<column_specification> receiver)
            : abstract_marker{bind_index, std::move(receiver)}
        { }
#if 0
        protected Marker(int bindIndex, ColumnSpecification receiver)
        {
            super(bindIndex, receiver);
            assert receiver.type instanceof SetType;
        }
#endif

        virtual ::shared_ptr<terminal> bind(const query_options& options) override {
            throw std::runtime_error("");
        }
#if 0
        public Value bind(QueryOptions options) throws InvalidRequestException
        {
            ByteBuffer value = options.getValues().get(bindIndex);
            return value == null ? null : Value.fromSerialized(value, (SetType)receiver.type, options.getProtocolVersion());
        }
#endif
    };

    class setter : public operation {
    public:
        setter(column_definition& column, shared_ptr<term> t)
                : operation(column, std::move(t)) {
        }

        virtual void execute(mutation& m, const clustering_prefix& row_key, const update_parameters& params) override {
            if (column.type->is_multi_cell()) {
                unimplemented::warn(unimplemented::cause::COLLECTION_RANGE_TOMBSTONES);
                // FIXME: implement
                // delete + add
#if 0
                CellName name = cf.getComparator().create(prefix, column);
                cf.addAtom(params.makeTombstoneForOverwrite(name.slice()));
#endif
            }
            adder::do_add(m, row_key, params, _t, column);
        }
    };

    class adder : public operation {
    public:
        adder(column_definition& column, shared_ptr<term> t)
            : operation(column, std::move(t)) {
        }

        virtual void execute(mutation& m, const clustering_prefix& row_key, const update_parameters& params) override {
            assert(column.type->is_multi_cell()); // "Attempted to add items to a frozen set";
            do_add(m, row_key, params, _t, column);
        }

        static void do_add(mutation& m, const clustering_prefix& row_key, const update_parameters& params,
                shared_ptr<term> t, const column_definition& column) {
            auto&& value = t->bind(params._options);
            auto set_value = dynamic_pointer_cast<sets::value>(std::move(value));
            auto set_type = dynamic_pointer_cast<set_type_impl>(column.type);
            if (column.type->is_multi_cell()) {
                if (!set_value || set_value->_elements.empty()) {
                    return;
                }

                // FIXME: mutation_view? not compatible with params.make_cell().
                collection_type_impl::mutation mut;
                for (auto&& e : set_value->_elements) {
                    mut.emplace_back(e, params.make_cell({}));
                }
                auto smut = set_type->serialize_mutation_form(mut);

                m.set_cell(row_key, column, std::move(smut));
            } else {
                // for frozen sets, we're overwriting the whole cell
                auto v = set_type->serialize_partially_deserialized_form(
                        {set_value->_elements.begin(), set_value->_elements.end()}, 3);
                if (set_value->_elements.empty()) {
                    m.set_cell(row_key, column, params.make_dead_cell());
                } else {
                    m.set_cell(row_key, column, params.make_cell(std::move(v)));
                }
            }
        }
    };

#if 0
    // Note that this is reused for Map subtraction too (we subtract a set from a map)
    public static class Discarder extends Operation
    {
        public Discarder(ColumnDefinition column, Term t)
        {
            super(column, t);
        }

        public void execute(ByteBuffer rowKey, ColumnFamily cf, Composite prefix, UpdateParameters params) throws InvalidRequestException
        {
            assert column.type.isMultiCell() : "Attempted to remove items from a frozen set";

            Term.Terminal value = t.bind(params.options);
            if (value == null)
                return;

            // This can be either a set or a single element
            Set<ByteBuffer> toDiscard = value instanceof Constants.Value
                                      ? Collections.singleton(((Constants.Value)value).bytes)
                                      : ((Sets.Value)value).elements;

            for (ByteBuffer bb : toDiscard)
            {
                cf.addColumn(params.makeTombstone(cf.getComparator().create(prefix, column, bb)));
            }
        }
    }
#endif
};

}

#endif
<|endoftext|>


<commit_before>#include <test/unit/math/test_ad.hpp>
#include <cmath>
#include <vector>

namespace cholesky_decompose_test {
// can't autodiff directly through Cholesky due to symmetry test;
// use unconstrained input and constrain to test Cholesky derivs;
// dof must be (n choose 2) + n
auto f(int dof) {
  return [=](const auto& x) {
    stan::math::promote_scalar_t<stan::value_type_t<decltype(x)>,
                                 Eigen::Matrix<double, -1, -1>>
        y;
    try {
      y = stan::math::cov_matrix_constrain(x, dof);
    } catch (...) {
      ADD_FAILURE() << "FAILED AT COV_MATRIX_CONSTRAIN";
      throw;
    }
    return stan::math::cholesky_decompose(y);
  };
}

auto f_matvar = [](const auto& x) { return stan::math::cholesky_decompose(x); };

void expect_cholesky(const Eigen::MatrixXd& Sigma) {
  Eigen::VectorXd yy = stan::math::cov_matrix_free(Sigma);
  // lazy, solving for x in x = (N * (N + 1)) / 2
  int dof = .5 * (std::sqrt(8 * yy.size() + 1) - 1);
  stan::test::expect_ad(f(dof), yy);
}
template <typename F, typename T>
void expect_cholesky_var(stan::test::ad_tolerances& tols, const F& f,
                         const T& x) {
  auto g = [&](const auto& v) {
    auto ds = stan::test::to_deserializer(v);
    auto xds = ds.read(x);
    return stan::test::serialize_return(stan::test::internal::eval(f(xds)));
  };
  auto x_serial = stan::test::serialize_args(x);
  auto h
      = [&](const int i) { return [&g, i](const auto& v) { return g(v)[i]; }; };
  size_t result_size = 0;
  try {
    auto y1
        = stan::test::internal::eval(f(x));  // original types, including int
    auto y2
        = stan::test::internal::eval(g(x_serial));  // all int cast to double
    auto y1_serial = stan::test::serialize<double>(y1);
    stan::test::expect_near_rel("expect_ad_helper", y1_serial, y2, 1e-10);
    result_size = y1_serial.size();
  } catch (...) {
    stan::test::internal::expect_all_throw(h(0), x_serial);
    return;
  }
  // we know the result is square and we only want to check lower half.
  size_t len = std::sqrt(result_size);
  for (size_t i = 0; i < len; ++i) {
    for (size_t j = 0; j < i; ++j) {
      double gx = h(i + len * j)(x_serial);
      stan::test::internal::test_gradient(tols, h(i + len * j), x_serial, gx);
    }
  }
}
}  // namespace cholesky_decompose_test

TEST(MathMixMatFun, choleskyDecomposeSpecific) {
  // 1 x 1 matrix;  (1 choose 2) + 1 = 1
  Eigen::VectorXd x1(1);
  x1 << 1;
  stan::test::expect_ad(cholesky_decompose_test::f(1), x1);
  Eigen::MatrixXd x1_mat = stan::math::cov_matrix_constrain(x1, 1);
  stan::test::expect_ad_matvar(cholesky_decompose_test::f_matvar, x1_mat);

  // 2 x 2 matrix;  (2 choose 2) + 2 = 3
  Eigen::VectorXd x3(3);
  x3 << 1, 2, -1;
  stan::test::expect_ad(cholesky_decompose_test::f(2), x3);
  Eigen::MatrixXd x3_mat = stan::math::cov_matrix_constrain(x3, 2);
  stan::test::expect_ad_matvar(cholesky_decompose_test::f_matvar, x3_mat);

  // 3 x 3 matrix;  (3 choose 2) + 3 = 6
  Eigen::VectorXd x6(6);
  x6 << 1, -1, 1.1, 1.4, 2.1, 0.7;
  stan::test::expect_ad(cholesky_decompose_test::f(3), x6);
  Eigen::MatrixXd x6_mat = stan::math::cov_matrix_constrain(x6, 3);
  stan::test::expect_ad_matvar(cholesky_decompose_test::f_matvar, x6_mat);

  // 4 x 4 matrix;  (4 choose 2) + 4 = 10
  Eigen::VectorXd x10(10);
  x10 << 1, -0.1, 1.1, 1.4, -1.1, 0.7, 1.0, 1.3, -0.5, 0.3;
  stan::test::expect_ad(cholesky_decompose_test::f(4), x10);
  Eigen::MatrixXd x10_mat = stan::math::cov_matrix_constrain(x10, 4);
  stan::test::expect_ad_matvar(cholesky_decompose_test::f_matvar, x10_mat);

  // 2 x 3 matrix will throw; test directly
  auto g = [](const auto& x) { return stan::math::cholesky_decompose(x); };
  Eigen::MatrixXd y(2, 3);
  y << 1, 2, 3, 4, 5, 6;
  stan::test::expect_ad(g, y);
  stan::test::expect_ad_matvar(g, y);

  // asymmetric will throw
  Eigen::MatrixXd z(2, 2);
  z << 1, 2, 3, 4;
  stan::test::expect_ad(g, z);
  stan::test::expect_ad_matvar(g, y);
}

TEST(MathMixMatFun, choleskyDecomposeGeneral) {
  // general sizes
  for (int n = 0; n < 8; ++n) {
    int dof = (n * (n + 1)) / 2;
    Eigen::VectorXd y(dof);
    for (int i = 0; i < dof; ++i)
      y(i) = (i * 10) / 10000.0;
    stan::test::ad_tolerances tol;
    using stan::test::relative_tolerance;
    stan::test::expect_ad(tol, cholesky_decompose_test::f(n), y);

    Eigen::MatrixXd y_mat = stan::math::cov_matrix_constrain(y, n);
    stan::test::expect_ad_matvar(cholesky_decompose_test::f_matvar, y_mat);
    stan::math::recover_memory();
  }
}

TEST(MathMixMatFun, choleskyDecomposeGeneralBig) {
  // general sizes
  for (double rho : std::vector<double>{0.0, 0.9}) {
    for (size_t m = 6; m < 8; ++m) {
      int n = std::pow(2, m) + 32;
      Eigen::MatrixXd Sigma(n, n);
      for (int i = 0; i < n; ++i) {
        Sigma(i, i) = 1;
        for (int j = 0; j < i; ++j) {
          Sigma(i, j) = std::pow(rho, fabs(i - j));
          Sigma(j, i) = Sigma(i, j);
        }
      }
      stan::test::ad_tolerances tol;
      using stan::test::relative_tolerance;
      tol.gradient_val_ = relative_tolerance(2e-2, 2e-1);
      tol.gradient_grad_ = relative_tolerance(2e-2, 2e-1);
      tol.hessian_hessian_ = relative_tolerance(2e-4, 2e-3);
      tol.hessian_fvar_hessian_ = relative_tolerance(2e-4, 2e-3);
      Eigen::VectorXd yy = stan::math::cov_matrix_free(Sigma);
      // lazy, solving for N in x = (N * (N + 1)) / 2
      int dof = .5 * (std::sqrt(8 * yy.size() + 1) - 1);
      cholesky_decompose_test::expect_cholesky_var(
          tol, cholesky_decompose_test::f(dof), yy);
      stan::test::expect_ad_matvar(cholesky_decompose_test::f_matvar, yy);
      stan::math::recover_memory();
    }
  }
}

// GP covar
TEST(MathMixMatFun, choleskyDecomposeGP) {
  for (size_t n = 1; n < 5; ++n) {
    std::vector<double> xx(n);
    for (size_t i = 0; i < n; ++i) {
      xx[i] = (i * 10) / 100.0;
    }
    double alpha = 0.75;
    double length_scale = 1.25;
    double jitter = 0.1;
    Eigen::MatrixXd Sigma = stan::math::add_diag(
        stan::math::cov_exp_quad(xx, alpha, length_scale), jitter);
    cholesky_decompose_test::expect_cholesky(Sigma);
    stan::test::expect_ad_matvar(cholesky_decompose_test::f_matvar, Sigma);
  }

  // time-series correlation
  for (double rho : std::vector<double>{0.0, 0.9}) {
    for (size_t n = 1; n < 5; ++n) {
      Eigen::MatrixXd Sigma(n, n);
      for (int i = 0; i < n; ++i) {
        Sigma(i, i) = 1;
        for (int j = 0; j < i; ++j) {
          Sigma(i, j) = std::pow(rho, fabs(i - j));
          Sigma(j, i) = Sigma(i, j);
        }
      }
      cholesky_decompose_test::expect_cholesky(Sigma);
      stan::test::expect_ad_matvar(cholesky_decompose_test::f_matvar, Sigma);
    }
  }
}
<commit_msg>fix loop order for checking lower half<commit_after>#include <test/unit/math/test_ad.hpp>
#include <cmath>
#include <vector>

namespace cholesky_decompose_test {
// can't autodiff directly through Cholesky due to symmetry test;
// use unconstrained input and constrain to test Cholesky derivs;
// dof must be (n choose 2) + n
auto f(int dof) {
  return [=](const auto& x) {
    stan::math::promote_scalar_t<stan::value_type_t<decltype(x)>,
                                 Eigen::Matrix<double, -1, -1>>
        y;
    try {
      y = stan::math::cov_matrix_constrain(x, dof);
    } catch (...) {
      ADD_FAILURE() << "FAILED AT COV_MATRIX_CONSTRAIN";
      throw;
    }
    return stan::math::cholesky_decompose(y);
  };
}

auto f_matvar = [](const auto& x) { return stan::math::cholesky_decompose(x); };

void expect_cholesky(const Eigen::MatrixXd& Sigma) {
  Eigen::VectorXd yy = stan::math::cov_matrix_free(Sigma);
  // lazy, solving for x in x = (N * (N + 1)) / 2
  int dof = .5 * (std::sqrt(8 * yy.size() + 1) - 1);
  stan::test::expect_ad(f(dof), yy);
}
template <typename F, typename T>
void expect_cholesky_var(stan::test::ad_tolerances& tols, const F& f,
                         const T& x) {
  auto g = [&](const auto& v) {
    auto ds = stan::test::to_deserializer(v);
    auto xds = ds.read(x);
    return stan::test::serialize_return(stan::test::internal::eval(f(xds)));
  };
  auto x_serial = stan::test::serialize_args(x);
  auto h
      = [&](const int i) { return [&g, i](const auto& v) { return g(v)[i]; }; };
  size_t result_size = 0;
  try {
    auto y1
        = stan::test::internal::eval(f(x));  // original types, including int
    auto y2
        = stan::test::internal::eval(g(x_serial));  // all int cast to double
    auto y1_serial = stan::test::serialize<double>(y1);
    stan::test::expect_near_rel("expect_ad_helper", y1_serial, y2, 1e-10);
    result_size = y1_serial.size();
  } catch (...) {
    stan::test::internal::expect_all_throw(h(0), x_serial);
    return;
  }
  // we know the result is square and we only want to check lower half.
  size_t len = std::sqrt(result_size);
  for (size_t j = 0; j < len; ++j) {
    for (size_t i = 0; i < j; ++i) {
      double gx = h(i + len * j)(x_serial);
      stan::test::internal::test_gradient(tols, h(i + len * j), x_serial, gx);
    }
  }
}
}  // namespace cholesky_decompose_test

TEST(MathMixMatFun, choleskyDecomposeSpecific) {
  // 1 x 1 matrix;  (1 choose 2) + 1 = 1
  Eigen::VectorXd x1(1);
  x1 << 1;
  stan::test::expect_ad(cholesky_decompose_test::f(1), x1);
  Eigen::MatrixXd x1_mat = stan::math::cov_matrix_constrain(x1, 1);
  stan::test::expect_ad_matvar(cholesky_decompose_test::f_matvar, x1_mat);

  // 2 x 2 matrix;  (2 choose 2) + 2 = 3
  Eigen::VectorXd x3(3);
  x3 << 1, 2, -1;
  stan::test::expect_ad(cholesky_decompose_test::f(2), x3);
  Eigen::MatrixXd x3_mat = stan::math::cov_matrix_constrain(x3, 2);
  stan::test::expect_ad_matvar(cholesky_decompose_test::f_matvar, x3_mat);

  // 3 x 3 matrix;  (3 choose 2) + 3 = 6
  Eigen::VectorXd x6(6);
  x6 << 1, -1, 1.1, 1.4, 2.1, 0.7;
  stan::test::expect_ad(cholesky_decompose_test::f(3), x6);
  Eigen::MatrixXd x6_mat = stan::math::cov_matrix_constrain(x6, 3);
  stan::test::expect_ad_matvar(cholesky_decompose_test::f_matvar, x6_mat);

  // 4 x 4 matrix;  (4 choose 2) + 4 = 10
  Eigen::VectorXd x10(10);
  x10 << 1, -0.1, 1.1, 1.4, -1.1, 0.7, 1.0, 1.3, -0.5, 0.3;
  stan::test::expect_ad(cholesky_decompose_test::f(4), x10);
  Eigen::MatrixXd x10_mat = stan::math::cov_matrix_constrain(x10, 4);
  stan::test::expect_ad_matvar(cholesky_decompose_test::f_matvar, x10_mat);

  // 2 x 3 matrix will throw; test directly
  auto g = [](const auto& x) { return stan::math::cholesky_decompose(x); };
  Eigen::MatrixXd y(2, 3);
  y << 1, 2, 3, 4, 5, 6;
  stan::test::expect_ad(g, y);
  stan::test::expect_ad_matvar(g, y);

  // asymmetric will throw
  Eigen::MatrixXd z(2, 2);
  z << 1, 2, 3, 4;
  stan::test::expect_ad(g, z);
  stan::test::expect_ad_matvar(g, y);
}

TEST(MathMixMatFun, choleskyDecomposeGeneral) {
  // general sizes
  for (int n = 0; n < 8; ++n) {
    int dof = (n * (n + 1)) / 2;
    Eigen::VectorXd y(dof);
    for (int i = 0; i < dof; ++i)
      y(i) = (i * 10) / 10000.0;
    stan::test::ad_tolerances tol;
    using stan::test::relative_tolerance;
    stan::test::expect_ad(tol, cholesky_decompose_test::f(n), y);

    Eigen::MatrixXd y_mat = stan::math::cov_matrix_constrain(y, n);
    stan::test::expect_ad_matvar(cholesky_decompose_test::f_matvar, y_mat);
    stan::math::recover_memory();
  }
}

TEST(MathMixMatFun, choleskyDecomposeGeneralBig) {
  // general sizes
  for (double rho : std::vector<double>{0.0, 0.9}) {
    for (size_t m = 6; m < 8; ++m) {
      int n = std::pow(2, m) + 32;
      Eigen::MatrixXd Sigma(n, n);
      for (int i = 0; i < n; ++i) {
        Sigma(i, i) = 1;
        for (int j = 0; j < i; ++j) {
          Sigma(i, j) = std::pow(rho, fabs(i - j));
          Sigma(j, i) = Sigma(i, j);
        }
      }
      stan::test::ad_tolerances tol;
      using stan::test::relative_tolerance;
      tol.gradient_val_ = relative_tolerance(2e-2, 2e-1);
      tol.gradient_grad_ = relative_tolerance(2e-2, 2e-1);
      tol.hessian_hessian_ = relative_tolerance(2e-4, 2e-3);
      tol.hessian_fvar_hessian_ = relative_tolerance(2e-4, 2e-3);
      Eigen::VectorXd yy = stan::math::cov_matrix_free(Sigma);
      // lazy, solving for N in x = (N * (N + 1)) / 2
      int dof = .5 * (std::sqrt(8 * yy.size() + 1) - 1);
      cholesky_decompose_test::expect_cholesky_var(
          tol, cholesky_decompose_test::f(dof), yy);
      stan::test::expect_ad_matvar(cholesky_decompose_test::f_matvar, yy);
      stan::math::recover_memory();
    }
  }
}

// GP covar
TEST(MathMixMatFun, choleskyDecomposeGP) {
  for (size_t n = 1; n < 5; ++n) {
    std::vector<double> xx(n);
    for (size_t i = 0; i < n; ++i) {
      xx[i] = (i * 10) / 100.0;
    }
    double alpha = 0.75;
    double length_scale = 1.25;
    double jitter = 0.1;
    Eigen::MatrixXd Sigma = stan::math::add_diag(
        stan::math::cov_exp_quad(xx, alpha, length_scale), jitter);
    cholesky_decompose_test::expect_cholesky(Sigma);
    stan::test::expect_ad_matvar(cholesky_decompose_test::f_matvar, Sigma);
  }

  // time-series correlation
  for (double rho : std::vector<double>{0.0, 0.9}) {
    for (size_t n = 1; n < 5; ++n) {
      Eigen::MatrixXd Sigma(n, n);
      for (int i = 0; i < n; ++i) {
        Sigma(i, i) = 1;
        for (int j = 0; j < i; ++j) {
          Sigma(i, j) = std::pow(rho, fabs(i - j));
          Sigma(j, i) = Sigma(i, j);
        }
      }
      cholesky_decompose_test::expect_cholesky(Sigma);
      stan::test::expect_ad_matvar(cholesky_decompose_test::f_matvar, Sigma);
    }
  }
}
<|endoftext|>


<commit_before>// include the Engine/entity/component interface
#include <Core/Geometry/MeshPrimitives.hpp>
#include <Engine/Scene/EntityManager.hpp>
#include <Engine/Scene/GeometryComponent.hpp>
#include <Engine/Scene/GeometrySystem.hpp>
// Include Radium base application and its simple Gui
#include <Gui/BaseApplication.hpp>
#include <Gui/RadiumWindow/SimpleWindowFactory.hpp>
#include <Gui/Viewer/TrackballCameraManipulator.hpp>
#include <Gui/Viewer/Viewer.hpp>

#include <QTimer>

//! [extend trackball]
// Add simple Camera Manipulator with only translation and zoom
class CameraManipulator2D : public Ra::Gui::TrackballCameraManipulator
{
  public:
    /// Default constructor
    inline CameraManipulator2D( uint width, uint height ) : Ra::Gui::TrackballCameraManipulator() {}

    /// Copy constructor used when switching camera manipulator
    /// Requires that m_target is on the line of sight of the camera.
    inline explicit CameraManipulator2D( const CameraManipulator& other ) :
        Ra::Gui::TrackballCameraManipulator( other ) {}

    inline bool handleMousePressEvent( QMouseEvent* event,
                                       const Qt::MouseButtons& buttons,
                                       const Qt::KeyboardModifiers& modifiers,
                                       int key ) {
        bool handled = false;
        m_lastMouseX = event->pos().x();
        m_lastMouseY = event->pos().y();

        auto action = Ra::Gui::KeyMappingManager::getInstance()->getAction(
            Ra::Gui::TrackballCameraManipulator::getContext(), buttons, modifiers, key, false );

        if ( action == TRACKBALLCAMERA_PAN )
        {
            m_cameraPanMode = true;
            handled         = true;
        }
        if ( action == TRACKBALLCAMERA_ZOOM )
        {
            m_cameraZoomMode = true;
            handled          = true;
        }

        return handled;
    }
};
//! [extend trackball]

int main( int argc, char* argv[] ) {
    //! [Creating the application]
    Ra::Gui::BaseApplication app( argc, argv );
    app.initialize( Ra::Gui::SimpleWindowFactory {} );
    //! [Creating the application]

    //! [Creating the cube]
    auto cube = Ra::Core::Geometry::makeSharpBox( {0.1f, 0.1f, 0.1f} );
    //! [Creating the cube]

    //! [Colorize the Cube]
    cube.addAttrib(
        "in_color",
        Ra::Core::Vector4Array {cube.vertices().size(), Ra::Core::Utils::Color::Green()} );
    //! [Colorize the Cube]

    //! [Create the engine entity for the cube]
    auto e = app.m_engine->getEntityManager()->createEntity( "Green cube" );
    //! [Create the engine entity for the cube]

    //! [Create a geometry component with the cube]
    auto c =
        new Ra::Engine::Scene::TriangleMeshComponent( "Cube Mesh", e, std::move( cube ), nullptr );
    //! [Create a geometry component with the cube]

    //! [Register the entity/component association to the geometry system ]
    auto geometrySystem = app.m_engine->getSystem( "GeometrySystem" );
    geometrySystem->addComponent( e, c );
    //! [Register the entity/component association to the geometry system ]

    //! [Tell the window that something is to be displayed]
    app.m_mainWindow->prepareDisplay();
    //! [Tell the window that something is to be displayed]

    //! [Install new manipulator]
    auto viewer = app.m_mainWindow->getViewer();
    viewer->setCameraManipulator( new CameraManipulator2D( *( viewer->getCameraManipulator() ) ) );
    //! [Install new manipulator]

    // terminate the app after 4 second (approximatively). Camera can be moved using mouse moves.
    auto close_timer = new QTimer( &app );
    close_timer->setInterval( 4000 );
    QObject::connect( close_timer, &QTimer::timeout, [&app]() { app.appNeedsToQuit(); } );
    close_timer->start();

    return app.exec();
}
<commit_msg>[tests] remove unneded screen size in ctor.<commit_after>// include the Engine/entity/component interface
#include <Core/Geometry/MeshPrimitives.hpp>
#include <Engine/Scene/EntityManager.hpp>
#include <Engine/Scene/GeometryComponent.hpp>
#include <Engine/Scene/GeometrySystem.hpp>
// Include Radium base application and its simple Gui
#include <Gui/BaseApplication.hpp>
#include <Gui/RadiumWindow/SimpleWindowFactory.hpp>
#include <Gui/Viewer/TrackballCameraManipulator.hpp>
#include <Gui/Viewer/Viewer.hpp>

#include <QTimer>

//! [extend trackball]
// Add simple Camera Manipulator with only translation and zoom
class CameraManipulator2D : public Ra::Gui::TrackballCameraManipulator
{
  public:
    /// Default constructor
    inline CameraManipulator2D() : Ra::Gui::TrackballCameraManipulator() {}

    /// Copy constructor used when switching camera manipulator
    /// Requires that m_target is on the line of sight of the camera.
    inline explicit CameraManipulator2D( const CameraManipulator& other ) :
        Ra::Gui::TrackballCameraManipulator( other ) {}

    inline bool handleMousePressEvent( QMouseEvent* event,
                                       const Qt::MouseButtons& buttons,
                                       const Qt::KeyboardModifiers& modifiers,
                                       int key ) {
        bool handled = false;
        m_lastMouseX = event->pos().x();
        m_lastMouseY = event->pos().y();

        auto action = Ra::Gui::KeyMappingManager::getInstance()->getAction(
            Ra::Gui::TrackballCameraManipulator::getContext(), buttons, modifiers, key, false );

        if ( action == TRACKBALLCAMERA_PAN )
        {
            m_cameraPanMode = true;
            handled         = true;
        }
        if ( action == TRACKBALLCAMERA_ZOOM )
        {
            m_cameraZoomMode = true;
            handled          = true;
        }

        return handled;
    }
};
//! [extend trackball]

int main( int argc, char* argv[] ) {
    //! [Creating the application]
    Ra::Gui::BaseApplication app( argc, argv );
    app.initialize( Ra::Gui::SimpleWindowFactory {} );
    //! [Creating the application]

    //! [Creating the cube]
    auto cube = Ra::Core::Geometry::makeSharpBox( {0.1f, 0.1f, 0.1f} );
    //! [Creating the cube]

    //! [Colorize the Cube]
    cube.addAttrib(
        "in_color",
        Ra::Core::Vector4Array {cube.vertices().size(), Ra::Core::Utils::Color::Green()} );
    //! [Colorize the Cube]

    //! [Create the engine entity for the cube]
    auto e = app.m_engine->getEntityManager()->createEntity( "Green cube" );
    //! [Create the engine entity for the cube]

    //! [Create a geometry component with the cube]
    auto c =
        new Ra::Engine::Scene::TriangleMeshComponent( "Cube Mesh", e, std::move( cube ), nullptr );
    //! [Create a geometry component with the cube]

    //! [Register the entity/component association to the geometry system ]
    auto geometrySystem = app.m_engine->getSystem( "GeometrySystem" );
    geometrySystem->addComponent( e, c );
    //! [Register the entity/component association to the geometry system ]

    //! [Tell the window that something is to be displayed]
    app.m_mainWindow->prepareDisplay();
    //! [Tell the window that something is to be displayed]

    //! [Install new manipulator]
    auto viewer = app.m_mainWindow->getViewer();
    viewer->setCameraManipulator( new CameraManipulator2D( *( viewer->getCameraManipulator() ) ) );
    //! [Install new manipulator]

    // terminate the app after 4 second (approximatively). Camera can be moved using mouse moves.
    auto close_timer = new QTimer( &app );
    close_timer->setInterval( 4000 );
    QObject::connect( close_timer, &QTimer::timeout, [&app]() { app.appNeedsToQuit(); } );
    close_timer->start();

    return app.exec();
}
<|endoftext|>


<commit_before>
#include <QtTest>
#include <QObject>
#include <QList>

#include <AST.h>
#include <ASTVisitor.h>
#include <TranslationUnit.h>
#include <CppBindings.h>
#include <CppDocument.h>
#include <FindUsages.h>
#include <Literals.h>
#include <LookupContext.h>
#include <Name.h>
#include <ResolveExpression.h>
#include <Symbols.h>
#include <Overview.h>

using namespace CPlusPlus;

class CollectNames: public ASTVisitor
{
public:
    CollectNames(TranslationUnit *xUnit): ASTVisitor(xUnit) {}
    QList<NameAST*> operator()(const char *name) {
        _name = name;
        _exprs.clear();

        accept(translationUnit()->ast());

        return _exprs;
    }

    virtual bool preVisit(AST *ast) {
        if (NameAST *nameAst = ast->asName())
            if (!qstrcmp(_name, nameAst->name->identifier()->chars()))
                _exprs.append(nameAst);
        return true;
    }

private:
    QList<NameAST*> _exprs;
    const char *_name;
};

class tst_FindUsages: public QObject
{
    Q_OBJECT

private Q_SLOTS:
    void inlineMethod();

    // Objective-C
    void objc_args();
//    void objc_methods();
//    void objc_fields();
//    void objc_classes();
};

void tst_FindUsages::inlineMethod()
{
    const QByteArray src = "\n"
                           "class Tst {\n"
                           "  int method(int arg) {\n"
                           "    return arg;\n"
                           "  }\n"
                           "};\n";
    Document::Ptr doc = Document::create("inlineMethod");
    doc->setSource(src);
    doc->parse();
    doc->check();

    QVERIFY(doc->diagnosticMessages().isEmpty());
    QCOMPARE(doc->globalSymbolCount(), 1U);

    Snapshot snapshot;
    snapshot.insert(doc);

    Class *tst = doc->globalSymbolAt(0)->asClass();
    QVERIFY(tst);
    QCOMPARE(tst->memberCount(), 1U);
    Function *method = tst->memberAt(0)->asFunction();
    QVERIFY(method);
    QCOMPARE(method->argumentCount(), 1U);
    Argument *arg = method->argumentAt(0)->asArgument();
    QVERIFY(arg);
    QCOMPARE(arg->identifier()->chars(), "arg");

    FindUsages findUsages(doc, snapshot);
    findUsages.setGlobalNamespaceBinding(bind(doc, snapshot));
    findUsages(arg);
    QCOMPARE(findUsages.usages().size(), 2);
    QCOMPARE(findUsages.references().size(), 2);
}

#if 0
@interface Clazz {} +(void)method:(int)arg; @end
@implementation Clazz +(void)method:(int)arg {
  [Clazz method:arg];
}
@end
#endif
const QByteArray objcSource = "\n"
                              "@interface Clazz {} +(void)method:(int)arg; @end\n"
                              "@implementation Clazz +(void)method:(int)arg {\n"
                              "  [Clazz method:arg];\n"
                              "}\n"
                              "@end\n";

void tst_FindUsages::objc_args()
{
    Document::Ptr doc = Document::create("objc_args");
    doc->setSource(objcSource);
    doc->parse();
    doc->check();

    QVERIFY(doc->diagnosticMessages().isEmpty());
    QCOMPARE(doc->globalSymbolCount(), 2U);

    Snapshot snapshot;
    snapshot.insert(doc);

    TranslationUnit *xUnit = doc->translationUnit();
    QList<NameAST*>exprs = CollectNames(xUnit)("arg");
    QCOMPARE(exprs.size(), 3);

    ObjCClass *iface = doc->globalSymbolAt(0)->asObjCClass();
    QVERIFY(iface);
    QVERIFY(iface->isInterface());
    QCOMPARE(iface->memberCount(), 1U);

    Declaration *methodIface = iface->memberAt(0)->asDeclaration();
    QVERIFY(methodIface);
    QCOMPARE(methodIface->identifier()->chars(), "method");
    QVERIFY(methodIface->type()->isObjCMethodType());

    ObjCClass *impl = doc->globalSymbolAt(1)->asObjCClass();
    QVERIFY(impl);
    QVERIFY(!impl->isInterface());
    QCOMPARE(impl->memberCount(), 1U);

    ObjCMethod *methodImpl = impl->memberAt(0)->asObjCMethod();
    QVERIFY(methodImpl);
    QCOMPARE(methodImpl->identifier()->chars(), "method");
    QCOMPARE(methodImpl->argumentCount(), 1U);
    Argument *arg = methodImpl->argumentAt(0)->asArgument();
    QCOMPARE(arg->identifier()->chars(), "arg");

    FindUsages findUsages(doc, snapshot);
    findUsages.setGlobalNamespaceBinding(bind(doc, snapshot));
    findUsages(arg);
    QCOMPARE(findUsages.usages().size(), 3);
    QCOMPARE(findUsages.references().size(), 3);
}

QTEST_APPLESS_MAIN(tst_FindUsages)
#include "tst_findusages.moc"
<commit_msg>Added unittest for FindUsages in Q_PROPERTY declarations.<commit_after>
#include <QtTest>
#include <QObject>
#include <QList>

#include <AST.h>
#include <ASTVisitor.h>
#include <TranslationUnit.h>
#include <CppBindings.h>
#include <CppDocument.h>
#include <FindUsages.h>
#include <Literals.h>
#include <LookupContext.h>
#include <Name.h>
#include <ResolveExpression.h>
#include <Symbols.h>
#include <Overview.h>

using namespace CPlusPlus;

class CollectNames: public ASTVisitor
{
public:
    CollectNames(TranslationUnit *xUnit): ASTVisitor(xUnit) {}
    QList<NameAST*> operator()(const char *name) {
        _name = name;
        _exprs.clear();

        accept(translationUnit()->ast());

        return _exprs;
    }

    virtual bool preVisit(AST *ast) {
        if (NameAST *nameAst = ast->asName())
            if (!qstrcmp(_name, nameAst->name->identifier()->chars()))
                _exprs.append(nameAst);
        return true;
    }

private:
    QList<NameAST*> _exprs;
    const char *_name;
};

class tst_FindUsages: public QObject
{
    Q_OBJECT

private Q_SLOTS:
    void inlineMethod();

    // Qt keywords
    void qproperty_1();

    // Objective-C
    void objc_args();
//    void objc_methods();
//    void objc_fields();
//    void objc_classes();
};

void tst_FindUsages::inlineMethod()
{
    const QByteArray src = "\n"
                           "class Tst {\n"
                           "  int method(int arg) {\n"
                           "    return arg;\n"
                           "  }\n"
                           "};\n";
    Document::Ptr doc = Document::create("inlineMethod");
    doc->setSource(src);
    doc->parse();
    doc->check();

    QVERIFY(doc->diagnosticMessages().isEmpty());
    QCOMPARE(doc->globalSymbolCount(), 1U);

    Snapshot snapshot;
    snapshot.insert(doc);

    Class *tst = doc->globalSymbolAt(0)->asClass();
    QVERIFY(tst);
    QCOMPARE(tst->memberCount(), 1U);
    Function *method = tst->memberAt(0)->asFunction();
    QVERIFY(method);
    QCOMPARE(method->argumentCount(), 1U);
    Argument *arg = method->argumentAt(0)->asArgument();
    QVERIFY(arg);
    QCOMPARE(arg->identifier()->chars(), "arg");

    FindUsages findUsages(doc, snapshot);
    findUsages.setGlobalNamespaceBinding(bind(doc, snapshot));
    findUsages(arg);
    QCOMPARE(findUsages.usages().size(), 2);
    QCOMPARE(findUsages.references().size(), 2);
}

#if 0
@interface Clazz {} +(void)method:(int)arg; @end
@implementation Clazz +(void)method:(int)arg {
  [Clazz method:arg];
}
@end
#endif
const QByteArray objcSource = "\n"
                              "@interface Clazz {} +(void)method:(int)arg; @end\n"
                              "@implementation Clazz +(void)method:(int)arg {\n"
                              "  [Clazz method:arg];\n"
                              "}\n"
                              "@end\n";

void tst_FindUsages::objc_args()
{
    Document::Ptr doc = Document::create("objc_args");
    doc->setSource(objcSource);
    doc->parse();
    doc->check();

    QVERIFY(doc->diagnosticMessages().isEmpty());
    QCOMPARE(doc->globalSymbolCount(), 2U);

    Snapshot snapshot;
    snapshot.insert(doc);

    TranslationUnit *xUnit = doc->translationUnit();
    QList<NameAST*>exprs = CollectNames(xUnit)("arg");
    QCOMPARE(exprs.size(), 3);

    ObjCClass *iface = doc->globalSymbolAt(0)->asObjCClass();
    QVERIFY(iface);
    QVERIFY(iface->isInterface());
    QCOMPARE(iface->memberCount(), 1U);

    Declaration *methodIface = iface->memberAt(0)->asDeclaration();
    QVERIFY(methodIface);
    QCOMPARE(methodIface->identifier()->chars(), "method");
    QVERIFY(methodIface->type()->isObjCMethodType());

    ObjCClass *impl = doc->globalSymbolAt(1)->asObjCClass();
    QVERIFY(impl);
    QVERIFY(!impl->isInterface());
    QCOMPARE(impl->memberCount(), 1U);

    ObjCMethod *methodImpl = impl->memberAt(0)->asObjCMethod();
    QVERIFY(methodImpl);
    QCOMPARE(methodImpl->identifier()->chars(), "method");
    QCOMPARE(methodImpl->argumentCount(), 1U);
    Argument *arg = methodImpl->argumentAt(0)->asArgument();
    QCOMPARE(arg->identifier()->chars(), "arg");

    FindUsages findUsages(doc, snapshot);
    findUsages.setGlobalNamespaceBinding(bind(doc, snapshot));
    findUsages(arg);
    QCOMPARE(findUsages.usages().size(), 2);
    QCOMPARE(findUsages.references().size(), 2);
}

void tst_FindUsages::qproperty_1()
{
    const QByteArray src = "\n"
                           "class Tst: public QObject {\n"
                           "  Q_PROPERTY(int x READ x WRITE setX NOTIFY xChanged)\n"
                           "public:\n"
                           "  int x() { return _x; }\n"
                           "  void setX(int x) { if (_x != x) { _x = x; emit xChanged(x); } }\n"
                           "signals:\n"
                           "  void xChanged(int);\n"
                           "private:\n"
                           "  int _x;\n"
                           "};\n";
    Document::Ptr doc = Document::create("qproperty_1");
    doc->setSource(src);
    doc->parse();
    doc->check();

    QVERIFY(doc->diagnosticMessages().isEmpty());
    QCOMPARE(doc->globalSymbolCount(), 1U);

    Snapshot snapshot;
    snapshot.insert(doc);

    Class *tst = doc->globalSymbolAt(0)->asClass();
    QVERIFY(tst);
    QCOMPARE(tst->memberCount(), 4U);
    Function *setX_method = tst->memberAt(1)->asFunction();
    QVERIFY(setX_method);
    QCOMPARE(setX_method->identifier()->chars(), "setX");
    QCOMPARE(setX_method->argumentCount(), 1U);

    FindUsages findUsages(doc, snapshot);
    findUsages.setGlobalNamespaceBinding(bind(doc, snapshot));
    findUsages(setX_method);
    QCOMPARE(findUsages.usages().size(), 2);
    QCOMPARE(findUsages.references().size(), 2);
}

QTEST_APPLESS_MAIN(tst_FindUsages)
#include "tst_findusages.moc"
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTest/QtTest>

#include <QtCore/QCoreApplication>
#include <QtCore/QSocketNotifier>
#include <QtNetwork/QTcpServer>
#include <QtNetwork/QTcpSocket>
#include <private/qnativesocketengine_p.h>

class tst_QSocketNotifier : public QObject
{
    Q_OBJECT
public:
    tst_QSocketNotifier();
    ~tst_QSocketNotifier();

private slots:
    void unexpectedDisconnection();
    void mixingWithTimers();
};

tst_QSocketNotifier::tst_QSocketNotifier()
{ }

tst_QSocketNotifier::~tst_QSocketNotifier()
{
}

class UnexpectedDisconnectTester : public QObject
{
    Q_OBJECT
public:
    QNativeSocketEngine *readEnd1, *readEnd2;
    int sequence;

    UnexpectedDisconnectTester(QNativeSocketEngine *s1, QNativeSocketEngine *s2)
        : readEnd1(s1), readEnd2(s2), sequence(0)
    {
        QSocketNotifier *notifier1 =
            new QSocketNotifier(readEnd1->socketDescriptor(), QSocketNotifier::Read, this);
        connect(notifier1, SIGNAL(activated(int)), SLOT(handleActivated()));
        QSocketNotifier *notifier2 =
            new QSocketNotifier(readEnd2->socketDescriptor(), QSocketNotifier::Read, this);
        connect(notifier2, SIGNAL(activated(int)), SLOT(handleActivated()));
    }

public slots:
    void handleActivated()
    {
        char data1[1], data2[1];
        ++sequence;
        if (sequence == 1) {
            // read from both ends
            (void) readEnd1->read(data1, sizeof(data1));
            (void) readEnd2->read(data2, sizeof(data2));
            emit finished();
        } else if (sequence == 2) {
            QCOMPARE(readEnd2->read(data2, sizeof(data2)), qint64(-2));
            QVERIFY(readEnd2->isValid());
        }
    }

signals:
    void finished();
};

void tst_QSocketNotifier::unexpectedDisconnection()
{
    /*
      Given two sockets and two QSocketNotifiers registered on each
      their socket. If both sockets receive data, and the first slot
      invoked by one of the socket notifiers empties both sockets, the
      other notifier will also emit activated(). This results in
      unexpected disconnection in QAbstractSocket.

      The use case is that somebody calls one of the
      waitFor... functions in a QSocketNotifier activated slot, and
      the waitFor... functions do local selects that can empty both
      stdin and stderr while waiting for fex bytes to be written.
    */

    QTcpServer server;
    QVERIFY(server.listen(QHostAddress::LocalHost, 0));

    QNativeSocketEngine readEnd1;
    readEnd1.initialize(QAbstractSocket::TcpSocket);
    bool b = readEnd1.connectToHost(server.serverAddress(), server.serverPort());
    QVERIFY(readEnd1.waitForWrite());
//    while (!b && readEnd1.state() != QAbstractSocket::ConnectedState)
//        b = readEnd1.connectToHost(server.serverAddress(), server.serverPort());
    QVERIFY(readEnd1.state() == QAbstractSocket::ConnectedState);
    QVERIFY(server.waitForNewConnection());
    QTcpSocket *writeEnd1 = server.nextPendingConnection();
    QVERIFY(writeEnd1 != 0);

    QNativeSocketEngine readEnd2;
    readEnd2.initialize(QAbstractSocket::TcpSocket);
    b = readEnd2.connectToHost(server.serverAddress(), server.serverPort());
    QVERIFY(readEnd2.waitForWrite());
//    while (!b)
//        b = readEnd2.connectToHost(server.serverAddress(), server.serverPort());
    QVERIFY(readEnd2.state() == QAbstractSocket::ConnectedState);
    QVERIFY(server.waitForNewConnection());
    QTcpSocket *writeEnd2 = server.nextPendingConnection();
    QVERIFY(writeEnd2 != 0);

    writeEnd1->write("1", 1);
    writeEnd2->write("2", 1);

    writeEnd1->waitForBytesWritten();
    writeEnd2->waitForBytesWritten();

    writeEnd1->flush();
    writeEnd2->flush();

    UnexpectedDisconnectTester tester(&readEnd1, &readEnd2);
    QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);

    QVERIFY(readEnd1.state() == QAbstractSocket::ConnectedState);
    QVERIFY(readEnd2.state() == QAbstractSocket::ConnectedState);
#if defined(Q_OS_WIN)
    qWarning("### Windows returns 1 activation, Unix returns 2.");
    QCOMPARE(tester.sequence, 1);
#else
    QCOMPARE(tester.sequence, 2);
#endif

    readEnd1.close();
    readEnd2.close();
    writeEnd1->close();
    writeEnd2->close();
    server.close();
}

class MixingWithTimersHelper : public QObject
{
    Q_OBJECT

public:
    MixingWithTimersHelper(QTimer *timer, QTcpServer *server);

    bool timerActivated;
    bool socketActivated;

private slots:
    void timerFired();
    void socketFired();
};

MixingWithTimersHelper::MixingWithTimersHelper(QTimer *timer, QTcpServer *server)
{
    timerActivated = false;
    socketActivated = false;

    connect(timer, SIGNAL(timeout()), SLOT(timerFired()));
    connect(server, SIGNAL(newConnection()), SLOT(socketFired()));
}

void MixingWithTimersHelper::timerFired()
{
    timerActivated = true;
}

void MixingWithTimersHelper::socketFired()
{
    socketActivated = true;
}

void tst_QSocketNotifier::mixingWithTimers()
{
    QTimer timer;
    timer.setInterval(0);
    timer.start();

    QTcpServer server;
    QVERIFY(server.listen(QHostAddress::LocalHost, 0));

    MixingWithTimersHelper helper(&timer, &server);

    QCoreApplication::processEvents();

    QCOMPARE(helper.timerActivated, true);
    QCOMPARE(helper.socketActivated, false);

    helper.timerActivated = false;
    helper.socketActivated = false;

    QTcpSocket socket;
    socket.connectToHost(server.serverAddress(), server.serverPort());

    QCoreApplication::processEvents();

    QCOMPARE(helper.timerActivated, true);
    QCOMPARE(helper.socketActivated, true);
}

QTEST_MAIN(tst_QSocketNotifier)
#include <tst_qsocketnotifier.moc>
<commit_msg>Any event can make us pass the line:     QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents) so we have to make sure that we wait for te right one to happen.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTest/QtTest>

#include <QtCore/QCoreApplication>
#include <QtCore/QSocketNotifier>
#include <QtNetwork/QTcpServer>
#include <QtNetwork/QTcpSocket>
#include <private/qnativesocketengine_p.h>

class tst_QSocketNotifier : public QObject
{
    Q_OBJECT
public:
    tst_QSocketNotifier();
    ~tst_QSocketNotifier();

private slots:
    void unexpectedDisconnection();
    void mixingWithTimers();
};

tst_QSocketNotifier::tst_QSocketNotifier()
{ }

tst_QSocketNotifier::~tst_QSocketNotifier()
{
}

class UnexpectedDisconnectTester : public QObject
{
    Q_OBJECT
    int sequence;

public:
    QNativeSocketEngine *readEnd1, *readEnd2;

    UnexpectedDisconnectTester(QNativeSocketEngine *s1, QNativeSocketEngine *s2)
        : readEnd1(s1), readEnd2(s2), sequence(0)
    {
        QSocketNotifier *notifier1 =
            new QSocketNotifier(readEnd1->socketDescriptor(), QSocketNotifier::Read, this);
        connect(notifier1, SIGNAL(activated(int)), SLOT(handleActivated()));
        QSocketNotifier *notifier2 =
            new QSocketNotifier(readEnd2->socketDescriptor(), QSocketNotifier::Read, this);
        connect(notifier2, SIGNAL(activated(int)), SLOT(handleActivated()));
    }

    const int getSequence() {
        return sequence;
    }

    void incSequence() {
        ++sequence;
    }

public slots:
    void handleActivated()
    {
        char data1[1], data2[1];
        incSequence();
        if (getSequence() == 1) {
            // read from both ends
            (void) readEnd1->read(data1, sizeof(data1));
            (void) readEnd2->read(data2, sizeof(data2));
            emit finished();
        } else if (getSequence() == 2) {
            QCOMPARE(readEnd2->read(data2, sizeof(data2)), qint64(-2));
            QVERIFY(readEnd2->isValid());
        }
    }

signals:
    void finished();
};

void tst_QSocketNotifier::unexpectedDisconnection()
{
    /*
      Given two sockets and two QSocketNotifiers registered on each
      their socket. If both sockets receive data, and the first slot
      invoked by one of the socket notifiers empties both sockets, the
      other notifier will also emit activated(). This results in
      unexpected disconnection in QAbstractSocket.

      The use case is that somebody calls one of the
      waitFor... functions in a QSocketNotifier activated slot, and
      the waitFor... functions do local selects that can empty both
      stdin and stderr while waiting for fex bytes to be written.
    */

    QTcpServer server;
    QVERIFY(server.listen(QHostAddress::LocalHost, 0));

    QNativeSocketEngine readEnd1;
    readEnd1.initialize(QAbstractSocket::TcpSocket);
    bool b = readEnd1.connectToHost(server.serverAddress(), server.serverPort());
    QVERIFY(readEnd1.waitForWrite());
//    while (!b && readEnd1.state() != QAbstractSocket::ConnectedState)
//        b = readEnd1.connectToHost(server.serverAddress(), server.serverPort());
    QVERIFY(readEnd1.state() == QAbstractSocket::ConnectedState);
    QVERIFY(server.waitForNewConnection());
    QTcpSocket *writeEnd1 = server.nextPendingConnection();
    QVERIFY(writeEnd1 != 0);

    QNativeSocketEngine readEnd2;
    readEnd2.initialize(QAbstractSocket::TcpSocket);
    b = readEnd2.connectToHost(server.serverAddress(), server.serverPort());
    QVERIFY(readEnd2.waitForWrite());
//    while (!b)
//        b = readEnd2.connectToHost(server.serverAddress(), server.serverPort());
    QVERIFY(readEnd2.state() == QAbstractSocket::ConnectedState);
    QVERIFY(server.waitForNewConnection());
    QTcpSocket *writeEnd2 = server.nextPendingConnection();
    QVERIFY(writeEnd2 != 0);

    writeEnd1->write("1", 1);
    writeEnd2->write("2", 1);

    writeEnd1->waitForBytesWritten();
    writeEnd2->waitForBytesWritten();

    writeEnd1->flush();
    writeEnd2->flush();

    UnexpectedDisconnectTester tester(&readEnd1, &readEnd2);

    do {
        // we have to wait until sequence value changes
        // as any event can make us jump out processing
        QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);
    }  while(tester.getSequence() <= 0);

    QVERIFY(readEnd1.state() == QAbstractSocket::ConnectedState);
    QVERIFY(readEnd2.state() == QAbstractSocket::ConnectedState);
#if defined(Q_OS_WIN)
    qWarning("### Windows returns 1 activation, Unix returns 2.");
    QCOMPARE(tester.sequence, 1);
#else
    QCOMPARE(tester.getSequence(), 2);
#endif

    readEnd1.close();
    readEnd2.close();
    writeEnd1->close();
    writeEnd2->close();
    server.close();
}

class MixingWithTimersHelper : public QObject
{
    Q_OBJECT

public:
    MixingWithTimersHelper(QTimer *timer, QTcpServer *server);

    bool timerActivated;
    bool socketActivated;

private slots:
    void timerFired();
    void socketFired();
};

MixingWithTimersHelper::MixingWithTimersHelper(QTimer *timer, QTcpServer *server)
{
    timerActivated = false;
    socketActivated = false;

    connect(timer, SIGNAL(timeout()), SLOT(timerFired()));
    connect(server, SIGNAL(newConnection()), SLOT(socketFired()));
}

void MixingWithTimersHelper::timerFired()
{
    timerActivated = true;
}

void MixingWithTimersHelper::socketFired()
{
    socketActivated = true;
}

void tst_QSocketNotifier::mixingWithTimers()
{
    QTimer timer;
    timer.setInterval(0);
    timer.start();

    QTcpServer server;
    QVERIFY(server.listen(QHostAddress::LocalHost, 0));

    MixingWithTimersHelper helper(&timer, &server);

    QCoreApplication::processEvents();

    QCOMPARE(helper.timerActivated, true);
    QCOMPARE(helper.socketActivated, false);

    helper.timerActivated = false;
    helper.socketActivated = false;

    QTcpSocket socket;
    socket.connectToHost(server.serverAddress(), server.serverPort());

    QCoreApplication::processEvents();

    QCOMPARE(helper.timerActivated, true);
    QCOMPARE(helper.socketActivated, true);
}

QTEST_MAIN(tst_QSocketNotifier)
#include <tst_qsocketnotifier.moc>
<|endoftext|>


<commit_before>#ifndef HAVE_LLVM
#error "This code needs LLVM enabled"
#endif

#include <set>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <cassert>
#include <cstdio>

// ignore unused parameters in LLVM libraries
#if (__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#else
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Instructions.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Support/raw_os_ostream.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/Support/CommandLine.h>

#if LLVM_VERSION_MAJOR >= 4
#include <llvm/Bitcode/BitcodeReader.h>
#include <llvm/Bitcode/BitcodeWriter.h>
#else
#include <llvm/Bitcode/ReaderWriter.h>
#endif

#if (__clang__)
#pragma clang diagnostic pop // ignore -Wunused-parameter
#else
#pragma GCC diagnostic pop
#endif

#include "dg/llvm/analysis/ValueRelations/ValueRelations.h"

#include "TimeMeasure.h"

using namespace dg::analysis;
using llvm::errs;

/*
static bool verbose = false;
static const char *entryFunc = "main";
*/

llvm::cl::opt<bool> todot("dot",
    llvm::cl::desc("Dump graph in grahviz format"), llvm::cl::init(false));

llvm::cl::opt<std::string> inputFile(llvm::cl::Positional, llvm::cl::Required,
    llvm::cl::desc("<input file>"), llvm::cl::init(""));

int main(int argc, char *argv[])
{
    llvm::Module *M;
    llvm::LLVMContext context;
    llvm::SMDiagnostic SMD;

    llvm::cl::ParseCommandLineOptions(argc, argv);

    if (inputFile.empty()) {
        errs() << "Usage: % IR_module\n";
        return 1;
    }

#if ((LLVM_VERSION_MAJOR == 3) && (LLVM_VERSION_MINOR <= 5))
    M = llvm::ParseIRFile(inputFile, SMD, context);
#else
    auto _M = llvm::parseIRFile(inputFile, SMD, context);
    // _M is unique pointer, we need to get Module *
    M = _M.get();
#endif

    if (!M) {
        llvm::errs() << "Failed parsing '" << inputFile << "' file:\n";
        SMD.print(argv[0], errs());
        return 1;
    }

    dg::debug::TimeMeasure tm;

    LLVMValueRelations VR(M);

    tm.start();

    VR.build();
    VR.compute();

    tm.stop();
    tm.report("INFO: Value Relations analysis took");

    std::cout << std::endl;

    if (todot) {
        std::cout << "digraph VR {\n";
        for (const auto& block : VR.getBlocks()) {
            for (const auto& loc : block.second->locations) {
                std::cout << "  NODE" << loc->id;
                std::cout << "[label=\"";
                std::cout << "\\n";
                loc->dump();
                std::cout << "\\n------ REL ------\\n";
                loc->relations.dump();
                std::cout << "\\n------ EQ ------\\n";
                loc->equalities.dump();
                std::cout << "\\n----- READS -----\\n";
                loc->reads.dump();
                std::cout << "\"];\n";
            }
        }

        for (const auto& block : VR.getBlocks()) {
            for (const auto& loc : block.second->locations) {
                for (const auto& succ : loc->successors) {
                    std::cout << "  NODE" << loc->id
                              << " -> NODE" << succ->target->id
                              << " [label=\"";
                    succ->op->dump();
                    std::cout << "\"];\n";
                }
            }
        }

        std::cout << "}\n";
    } else {
        for (auto& F : *M) {
            for (auto& B : F) {
                for (auto& I : B) {
                    auto loc = VR.getMapping(&I);
                    if (!loc)
                        continue;

                    std::cout << "==============================================\n";
                    std::cout << debug::getValName(&I) << "\n";
                    std::cout << "==============================================";
                    std::cout << "\n------ REL ------\n";
                    loc->relations.dump();
                    std::cout << "\n------ EQ ------\n";
                    loc->equalities.dump();
                    std::cout << "\n----- READS -----\n";
                    loc->reads.dump();
                    std::cout << "\n";
                }
            }
        }
    }

    return 0;
}
<commit_msg>Fix Release build<commit_after>#ifndef HAVE_LLVM
#error "This code needs LLVM enabled"
#endif

#include <set>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <cassert>
#include <cstdio>

// ignore unused parameters in LLVM libraries
#if (__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#else
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Instructions.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Support/raw_os_ostream.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/Support/CommandLine.h>

#if LLVM_VERSION_MAJOR >= 4
#include <llvm/Bitcode/BitcodeReader.h>
#include <llvm/Bitcode/BitcodeWriter.h>
#else
#include <llvm/Bitcode/ReaderWriter.h>
#endif

#if (__clang__)
#pragma clang diagnostic pop // ignore -Wunused-parameter
#else
#pragma GCC diagnostic pop
#endif

#undef NDEBUG // we need dump methods
#include "dg/llvm/analysis/ValueRelations/ValueRelations.h"

#include "TimeMeasure.h"

using namespace dg::analysis;
using llvm::errs;

/*
static bool verbose = false;
static const char *entryFunc = "main";
*/

llvm::cl::opt<bool> todot("dot",
    llvm::cl::desc("Dump graph in grahviz format"), llvm::cl::init(false));

llvm::cl::opt<std::string> inputFile(llvm::cl::Positional, llvm::cl::Required,
    llvm::cl::desc("<input file>"), llvm::cl::init(""));

int main(int argc, char *argv[])
{
    llvm::Module *M;
    llvm::LLVMContext context;
    llvm::SMDiagnostic SMD;

    llvm::cl::ParseCommandLineOptions(argc, argv);

    if (inputFile.empty()) {
        errs() << "Usage: % IR_module\n";
        return 1;
    }

#if ((LLVM_VERSION_MAJOR == 3) && (LLVM_VERSION_MINOR <= 5))
    M = llvm::ParseIRFile(inputFile, SMD, context);
#else
    auto _M = llvm::parseIRFile(inputFile, SMD, context);
    // _M is unique pointer, we need to get Module *
    M = _M.get();
#endif

    if (!M) {
        llvm::errs() << "Failed parsing '" << inputFile << "' file:\n";
        SMD.print(argv[0], errs());
        return 1;
    }

    dg::debug::TimeMeasure tm;

    LLVMValueRelations VR(M);

    tm.start();

    VR.build();
    VR.compute();

    tm.stop();
    tm.report("INFO: Value Relations analysis took");

    std::cout << std::endl;

    if (todot) {
        std::cout << "digraph VR {\n";
        for (const auto& block : VR.getBlocks()) {
            for (const auto& loc : block.second->locations) {
                std::cout << "  NODE" << loc->id;
                std::cout << "[label=\"";
                std::cout << "\\n";
                loc->dump();
                std::cout << "\\n------ REL ------\\n";
                loc->relations.dump();
                std::cout << "\\n------ EQ ------\\n";
                loc->equalities.dump();
                std::cout << "\\n----- READS -----\\n";
                loc->reads.dump();
                std::cout << "\"];\n";
            }
        }

        for (const auto& block : VR.getBlocks()) {
            for (const auto& loc : block.second->locations) {
                for (const auto& succ : loc->successors) {
                    std::cout << "  NODE" << loc->id
                              << " -> NODE" << succ->target->id
                              << " [label=\"";
                    succ->op->dump();
                    std::cout << "\"];\n";
                }
            }
        }

        std::cout << "}\n";
    } else {
        for (auto& F : *M) {
            for (auto& B : F) {
                for (auto& I : B) {
                    auto loc = VR.getMapping(&I);
                    if (!loc)
                        continue;

                    std::cout << "==============================================\n";
                    std::cout << debug::getValName(&I) << "\n";
                    std::cout << "==============================================";
                    std::cout << "\n------ REL ------\n";
                    loc->relations.dump();
                    std::cout << "\n------ EQ ------\n";
                    loc->equalities.dump();
                    std::cout << "\n----- READS -----\n";
                    loc->reads.dump();
                    std::cout << "\n";
                }
            }
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>#include <Pop/Pop.hpp>
#include <cassert>
#include <iostream>

using namespace Pop;

int main() {
  Compiler cmp;
  cmp.parse_file("test.pop"); // 0
  cmp.link_parents(true);     // 1
  cmp.define_symbols();       // 2
  cmp.resolve_symbols();      // 3
  cmp.patch_locations(true);  // 4
  cmp.validate();             // 5
  cmp.generate_dot(std::cout);
  assert(cmp.report_diagnostics(std::cerr) == 0);
  return 0;
}
<commit_msg>Reorder passes a bit<commit_after>#include <Pop/Pop.hpp>
#include <cassert>
#include <iostream>

using namespace Pop;

int main() {
  Compiler cmp;
  cmp.parse_file("test.pop");
  cmp.patch_locations(true);
  cmp.link_parents(true);
  cmp.define_symbols();
  cmp.resolve_symbols();
  cmp.validate();
  cmp.generate_dot(std::cout);
  assert(cmp.report_diagnostics(std::cerr) == 0);
  return 0;
}
<|endoftext|>


<commit_before>#include "InetAddress.h"

#include <memory>

#include <assert.h>
#include <arpa/inet.h>
#include <netdb.h>

static_assert(sizeof(InetAddress) == sizeof(struct sockaddr_in6),
              "InetAddress is same size as sockaddr_in6");
static_assert(offsetof(sockaddr_in, sin_family) == 0, "sin_family offset 0");
static_assert(offsetof(sockaddr_in6, sin6_family) == 0, "sin6_family offset 0");
static_assert(offsetof(sockaddr_in, sin_port) == 2, "sin_port offset 2");
static_assert(offsetof(sockaddr_in6, sin6_port) == 2, "sin6_port offset 2");

InetAddress::InetAddress(StringArg ip, uint16_t port)
{
  setPort(port);

  int result = 0;
  if (strchr(ip.c_str(), ':') == NULL)
  {
    result = ::inet_pton(AF_INET, ip.c_str(), &addr_.sin_addr);
  }
  else
  {
    result = ::inet_pton(AF_INET6, ip.c_str(), &addr6_.sin6_addr);
  }

  assert(result == 1 && "Invalid IP format");
}

InetAddress::InetAddress(uint16_t port, bool ipv6)
{
  static_assert(offsetof(InetAddress, addr6_) == 0, "addr6_ offset 0");
  static_assert(offsetof(InetAddress, addr_) == 0, "addr_ offset 0");
  bool loopbackOnly = false;
  if (ipv6)
  {
    memZero(&addr6_, sizeof addr6_);
    addr6_.sin6_family = AF_INET6;
    in6_addr ip = loopbackOnly ? in6addr_loopback : in6addr_any;
    addr6_.sin6_addr = ip;
    addr6_.sin6_port = htons(port);
  }
  else
  {
    memZero(&addr_, sizeof addr_);
    addr_.sin_family = AF_INET;
    in_addr_t ip = loopbackOnly ? INADDR_LOOPBACK : INADDR_ANY;
    addr_.sin_addr.s_addr = htonl(ip);
    addr_.sin_port = htons(port);
  }
}

InetAddress::InetAddress(const struct sockaddr& saddr)
{
  if (saddr.sa_family == AF_INET)
  {
    memcpy(&addr_, &saddr, sizeof addr_);
  }
  else if (saddr.sa_family == AF_INET6)
  {
    memcpy(&addr6_, &saddr, sizeof addr6_);
  }
  else
  {
    assert(false);
  }
}

std::string InetAddress::toIp() const
{
  char buf[64] = "";
  static_assert(sizeof buf >= INET_ADDRSTRLEN);
  static_assert(sizeof buf >= INET6_ADDRSTRLEN);

  if (family() == AF_INET)
  {
    ::inet_ntop(AF_INET, &addr_.sin_addr, buf, static_cast<socklen_t>(sizeof buf));
  }
  else if (family() == AF_INET6)
  {
    ::inet_ntop(AF_INET6, &addr6_.sin6_addr, buf, static_cast<socklen_t>(sizeof buf));
  }

  return buf;
}

std::string InetAddress::toIpPort() const
{
  char buf[32] = "";
  snprintf(buf, sizeof buf, ":%u", port());
  return toIp() + buf;
}

bool InetAddress::operator==(const InetAddress& rhs) const
{
  if (family() == rhs.family())
  {
    if (family() == AF_INET)
    {
      return addr_.sin_port == rhs.addr_.sin_port &&
          addr_.sin_addr.s_addr == rhs.addr_.sin_addr.s_addr;
    }
    else if (family() == AF_INET6)
    {
      return addr6_.sin6_port == rhs.addr6_.sin6_port &&
          memcmp(&addr6_.sin6_addr, &rhs.addr6_.sin6_addr, sizeof addr6_.sin6_addr) == 0;
    }
  }
  return false;
}

// static
bool InetAddress::resolve(StringArg hostname, uint16_t port, InetAddress* out)
{
  assert(out);
  std::vector<InetAddress> addrs = resolveAll(hostname, port);

  if (addrs.empty())
    return false;

  // Read the first result
  *out = addrs[0];

  return true;
}

// static
std::vector<InetAddress> InetAddress::resolveAll(StringArg hostname, uint16_t port)
{
  std::vector<InetAddress> addrs;

  struct addrinfo* result = NULL;
  int error = getaddrinfo(hostname.c_str(), NULL, NULL, &result);
  if (error != 0)
  {
    if (error == EAI_SYSTEM)
    {
      perror("InetAddress::resolve");
    }
    else
    {
      fprintf(stderr, "InetAddress::resolve: %s\n", gai_strerror(error));
    }
    return addrs;
  }

  assert(result);
  std::unique_ptr<struct addrinfo, decltype(&freeaddrinfo)> freeResult(result, freeaddrinfo);

  for (struct addrinfo* ai = result; ai != NULL; ai = ai->ai_next)
  {
    InetAddress addr(*ai->ai_addr);
    addr.setPort(port);
    addrs.push_back(addr);
  }
  return addrs;
}
<commit_msg>Fix InetAddress::toIpPort() for IPv6<commit_after>#include "InetAddress.h"

#include <memory>

#include <assert.h>
#include <arpa/inet.h>
#include <netdb.h>

static_assert(sizeof(InetAddress) == sizeof(struct sockaddr_in6),
              "InetAddress is same size as sockaddr_in6");
static_assert(offsetof(sockaddr_in, sin_family) == 0, "sin_family offset 0");
static_assert(offsetof(sockaddr_in6, sin6_family) == 0, "sin6_family offset 0");
static_assert(offsetof(sockaddr_in, sin_port) == 2, "sin_port offset 2");
static_assert(offsetof(sockaddr_in6, sin6_port) == 2, "sin6_port offset 2");

InetAddress::InetAddress(StringArg ip, uint16_t port)
{
  setPort(port);

  int result = 0;
  if (strchr(ip.c_str(), ':') == NULL)
  {
    result = ::inet_pton(AF_INET, ip.c_str(), &addr_.sin_addr);
  }
  else
  {
    result = ::inet_pton(AF_INET6, ip.c_str(), &addr6_.sin6_addr);
  }

  assert(result == 1 && "Invalid IP format");
}

InetAddress::InetAddress(uint16_t port, bool ipv6)
{
  static_assert(offsetof(InetAddress, addr6_) == 0, "addr6_ offset 0");
  static_assert(offsetof(InetAddress, addr_) == 0, "addr_ offset 0");
  bool loopbackOnly = false;
  if (ipv6)
  {
    memZero(&addr6_, sizeof addr6_);
    addr6_.sin6_family = AF_INET6;
    in6_addr ip = loopbackOnly ? in6addr_loopback : in6addr_any;
    addr6_.sin6_addr = ip;
    addr6_.sin6_port = htons(port);
  }
  else
  {
    memZero(&addr_, sizeof addr_);
    addr_.sin_family = AF_INET;
    in_addr_t ip = loopbackOnly ? INADDR_LOOPBACK : INADDR_ANY;
    addr_.sin_addr.s_addr = htonl(ip);
    addr_.sin_port = htons(port);
  }
}

InetAddress::InetAddress(const struct sockaddr& saddr)
{
  if (saddr.sa_family == AF_INET)
  {
    memcpy(&addr_, &saddr, sizeof addr_);
  }
  else if (saddr.sa_family == AF_INET6)
  {
    memcpy(&addr6_, &saddr, sizeof addr6_);
  }
  else
  {
    assert(false);
  }
}

std::string InetAddress::toIp() const
{
  char buf[64] = "";
  static_assert(sizeof buf >= INET_ADDRSTRLEN);
  static_assert(sizeof buf >= INET6_ADDRSTRLEN);

  if (family() == AF_INET)
  {
    ::inet_ntop(AF_INET, &addr_.sin_addr, buf, static_cast<socklen_t>(sizeof buf));
  }
  else if (family() == AF_INET6)
  {
    ::inet_ntop(AF_INET6, &addr6_.sin6_addr, buf, static_cast<socklen_t>(sizeof buf));
  }

  return buf;
}

std::string InetAddress::toIpPort() const
{
  char buf[32] = "";
  snprintf(buf, sizeof buf, ":%u", port());

  if (family() == AF_INET6)
    return "[" + toIp() + "]" + buf;

  return toIp() + buf;
}

bool InetAddress::operator==(const InetAddress& rhs) const
{
  if (family() == rhs.family())
  {
    if (family() == AF_INET)
    {
      return addr_.sin_port == rhs.addr_.sin_port &&
          addr_.sin_addr.s_addr == rhs.addr_.sin_addr.s_addr;
    }
    else if (family() == AF_INET6)
    {
      return addr6_.sin6_port == rhs.addr6_.sin6_port &&
          memcmp(&addr6_.sin6_addr, &rhs.addr6_.sin6_addr, sizeof addr6_.sin6_addr) == 0;
    }
  }
  return false;
}

// static
bool InetAddress::resolve(StringArg hostname, uint16_t port, InetAddress* out)
{
  assert(out);
  std::vector<InetAddress> addrs = resolveAll(hostname, port);

  if (addrs.empty())
    return false;

  // Read the first result
  *out = addrs[0];

  return true;
}

// static
std::vector<InetAddress> InetAddress::resolveAll(StringArg hostname, uint16_t port)
{
  std::vector<InetAddress> addrs;

  struct addrinfo* result = NULL;
  int error = getaddrinfo(hostname.c_str(), NULL, NULL, &result);
  if (error != 0)
  {
    if (error == EAI_SYSTEM)
    {
      perror("InetAddress::resolve");
    }
    else
    {
      fprintf(stderr, "InetAddress::resolve: %s\n", gai_strerror(error));
    }
    return addrs;
  }

  assert(result);
  std::unique_ptr<struct addrinfo, decltype(&freeaddrinfo)> freeResult(result, freeaddrinfo);

  for (struct addrinfo* ai = result; ai != NULL; ai = ai->ai_next)
  {
    InetAddress addr(*ai->ai_addr);
    addr.setPort(port);
    addrs.push_back(addr);
  }
  return addrs;
}
<|endoftext|>