The Sort Test Code of Supersonic

// Copyright 2012 Google Inc. All Rights Reserved.
// Author: tomasz.kaftal@gmail.com (Tomasz Kaftal)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// This tutorial is the second in the guide and it picks up where primer.cc left
// off. For more information see the README file in this directory.
//
// The file contains two larger test cases which cover more complex
// aggregations and sorting. Basic memory management will also be touched
// upon including creating StringPiece objects using a memory arena.


#include <algorithm>
using std::copy;
using std::max;
using std::min;
using std::reverse;
using std::sort;
using std::swap;
#include <map>
using std::map;
using std::multimap;
#include <set>
using std::multiset;
using std::set;
#include <utility>
using std::make_pair;
using std::pair;


#include "gtest/gtest.h"


#include "supersonic/supersonic.h"
#include "supersonic/cursor/core/sort.h"
#include "supersonic/cursor/infrastructure/ordering.h"
#include "supersonic/utils/strings/stringpiece.h"


// Include some map utilities to use for result verification.
#include "supersonic/utils/map-util.h"


using supersonic::TupleSchema;
using supersonic::View;
using supersonic::ResultView;
using supersonic::Attribute;
using supersonic::Arena;
using supersonic::AggregationSpecification;
using supersonic::Operation;
using supersonic::CompoundSingleSourceProjector;
using supersonic::SingleSourceProjector;
using supersonic::ProjectNamedAttribute;
using supersonic::ProjectNamedAttributeAs;
using supersonic::ProjectAttributeAt;
using supersonic::GroupAggregate;
using supersonic::Cursor;
using supersonic::SucceedOrDie;
using supersonic::Block;
using supersonic::HeapBufferAllocator;
using supersonic::ViewCopier;
using supersonic::NO_SELECTOR;


using supersonic::MAX;
using supersonic::MIN;


using supersonic::INT32;
using supersonic::NOT_NULLABLE;
using supersonic::STRING;
using supersonic::BOOL;
using supersonic::DOUBLE;


using supersonic::SortOrder;
using supersonic::Sort;
using supersonic::ASCENDING;




class SortingTest {
public:
   void SetUp() {
    // Simple two-column schema to use for sorting by the "grade" attribute.
    schema.add_attribute(Attribute("id", INT32, NOT_NULLABLE));
    schema.add_attribute(Attribute("grade", DOUBLE, NOT_NULLABLE));


    input_view.reset(new View(schema));
  }


  void PrepareSort() {
    // First, we'll need to specify the column by which the sorting should be
    // carried out. To do it we once again employ a single source projector.
    scoped_ptr<const SingleSourceProjector>
        projector(ProjectNamedAttribute("grade"));


    scoped_ptr<SortOrder> sort_order(new SortOrder());
    sort_order->add(projector.release(), ASCENDING);


    const size_t mem_limit = 128;


    scoped_ptr<Operation> sort(Sort(sort_order.release(),
                                   NULL,
                                    mem_limit,
                                    ScanView(*input_view)));


    result_cursor.reset(SucceedOrDie(sort->CreateCursor()));
  }


  void LoadData(const int32* ids,
                const double* grades,
                size_t row_count) {
    // Load up the data columns.
    input_view->set_row_count(row_count);
    input_view->mutable_column(0)->Reset(ids, NULL);
    input_view->mutable_column(1)->Reset(grades, NULL);
  }


  typedef pair<int32, double> entry;
  typedef map<entry, int32>::const_iterator entry_it;


  void TestResults(const int32* ids,
                   const double* grades,
                   size_t row_count) {


    scoped_ptr<Block> result_space(new Block(schema,
                                             HeapBufferAllocator::Get()));
    result_space->Reallocate(row_count);




    ViewCopier copier(schema, /* deep copy */ true);


    unsigned offset = 0;


    // Create a result view much like before.
    scoped_ptr<ResultView> rv(new ResultView(result_cursor->Next(1024)));


    while (!rv->is_done()) {
      const View& view = rv->view();
      unsigned view_row_count = view.row_count();


      unsigned rows_copied = copier.Copy(view_row_count,
                                         view,
                                         offset,
                                         result_space.get());


      // The returned number of copied rows will match the specified
      // count, unless there have been allocation errors.
  //    EXPECT_EQ(view_row_count, rows_copied);


      offset += rows_copied;
      rv.reset(new ResultView(result_cursor->Next(1024)));
    }


    const View& result_view(result_space->view());


  //  ASSERT_EQ(2, result_view.column_count());
  //  ASSERT_EQ(row_count, result_view.row_count());


    // Test if the result data is correctly sorted. Previous assertions
    // will fail if there are no results.
    /*for (unsigned i = 1; i < row_count; ++i) {
      EXPECT_TRUE(result_view.column(1).typed_data<DOUBLE>()[i] >=
          result_view.column(1).typed_data<DOUBLE>()[i - 1]);
    }*/


    // Check if the sorted entries are exactly the ones we
    // received as input.
    map<entry, int32> occurences;
    for (unsigned i = 0; i < row_count; ++i) {
      entry key(ids[i], grades[i]);
      if (!ContainsKey(occurences, key)) {
        occurences[key] = 0;
      }
      occurences[key]++;
    }


  /*  for (unsigned i = 0; i < row_count; ++i) {
      entry key(result_view.column(0).typed_data<INT32>()[i],
                result_view.column(1).typed_data<DOUBLE>()[i]);
      EXPECT_TRUE(ContainsKey(occurences, key)) << "Invalid value ("
          << key.first
          << ", "
          << key.second
          << ") appeared during sorting!";
      occurences[key]--;
    }*/


 /*   for (entry_it it = occurences.begin(); it != occurences.end(); ++it) {
      EXPECT_EQ(0, it->second) << "Value ("
          << it->first.first
          << ", "
          << it->first.second
          << ") invalidly "
          << (it->second > 0 ? "removed" : "created")
          << " during sorting!";
    }*/
  }


  // Supersonic objects.
  scoped_ptr<Cursor> result_cursor;
  TupleSchema schema;
  scoped_ptr<View> input_view;
};


int main(void) {
  // Data set for sorting.
  const unsigned row_count = 8;
  int32 ids[row_count] = {1, 2, 3, 4, 5, 6, 7, 8};
  double grades[row_count] = {4.5, 4.2, 3.5, 4.8, 4.2, 3.9, 3.2, 4.8};
  SortingTest sorttest;
  sorttest.LoadData(ids, grades, row_count);
  sorttest.PrepareSort();
  sorttest.TestResults(ids, grades, row_count);
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值