# coding: utf-8 require 'spec_helper' require 'open3' require 'mysql2' require 'flydata/command/sync' require 'flydata/source_mysql/parser/dump_parser' require 'flydata-core/mysql/binlog_pos' module Flydata module SourceMysql module Parser context "Test Dump Generators" do let(:stdin) do s = double(:stdin) allow(s).to receive(:close_write) s end let(:stdout) do s = double(:stdout) allow(s).to receive(:set_encoding) allow(s).to receive(:wait_readable) allow(s).to receive(:each_line).and_yield("another line") s end let(:file_path) { File.join('/tmp', "flydata_sync_spec_mysqldump_#{Time.now.to_i}") } let(:default_conf) do { 'host' => 'localhost', 'port' => 3306, 'username' => 'admin', 'password' => 'pass', 'database' => 'dev', 'tables' => ['users','groups'], } end describe MysqlDumpGeneratorNoMasterData do let(:subject_object) { described_class.new(default_conf) } let(:stderr) { double(:stderr) } let(:wait_thr) { double(:wait_thr) } let(:default_dump_generator) { subject_object } let(:binlog_pos) { { binfile: 'mysql-bin.000451', pos: 89872 } } let(:mysql_client) do m = double(:mysql_client) allow(m).to receive(:query).with(/TABLES/) allow(m).to receive(:query).with("SHOW VARIABLES LIKE 'version'"). and_return([{'Value' => '5.1.40-0ubuntu0.12.04.1-log'}]) allow(m).to receive(:query).with("FLUSH TABLES WITH READ LOCK;", {retry_count:-1, retry_interval:1}) allow(m).to receive(:query).with("SHOW MASTER STATUS;"). and_return([{'File' => 'mysql-bin.000451', 'Position' => 89872}]) allow(m).to receive(:thread_id).and_return(1191) allow(m).to receive(:close) m end describe '#dump' do before do expect(Mysql2::Client).to receive(:new).and_return(mysql_client) expect(Open3).to receive(:popen3).and_yield(stdin, stdout, stderr, wait_thr) allow(File).to receive(:size?).and_return true end context "when mysqldump exits with status 0" do it do expect(wait_thr).to receive(:value).and_return(0) expect(stderr).to receive(:each_line).and_yield("") expect(default_dump_generator.dump(file_path)).to eq(binlog_pos) end end context "when mysqldump exits with status 1" do it do expect(wait_thr).to receive(:value).and_return(1) expect(stderr).to receive(:each_line).and_yield("") expect{ default_dump_generator.dump(file_path) }.to raise_error end end context "when mysqldump exits with status 0, but there are error in stderr" do it do expect(wait_thr).to receive(:value).and_return(0) expect(stderr).to receive(:each_line).and_yield("mysqldump error") expect{ default_dump_generator.dump(file_path) }.to raise_error end end after :each do File.delete(file_path) if File.exists?(file_path) end end describe '#flush_tables_with_read_lock_query' do subject { subject_object.send(:flush_tables_with_read_lock_query, client, database, tbls) } let(:client) { double('client') } let(:database) { "db1" } let(:tbls) { ['table1'] } before do allow(subject_object).to receive(:mysql_server_version). and_return(version) end let(:flush_tables_with_tables) { <--5.6.13-log /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; /*!40101 SET NAMES utf8 */; /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -- -- Position to start replication or point-in-time recovery from -- -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000267', MASTER_LOG_POS=120; EOT def index_after(content, string) content[0...content.index(string)].bytesize + string.bytesize + 1 end let(:default_parser) { MysqlDumpParser.new(source_pos: default_binlog_pos_object) } let(:default_binlog_pos) { {binfile: 'mysql-bin.000267', pos: 120 } } let(:default_binlog_pos_object) { FlydataCore::Mysql::BinlogPos.new(default_binlog_pos) } let(:dump_pos_after_binlog_pos) { index_after(DUMP_HEADER, '5.6.13-log') } let(:create_table_block) { double('create_table_block') } let(:insert_record_block) { double('insert_record_block') } let(:check_point_block) { double('check_point_block') } before do generate_dump_file('') end context 'when dump contains only binlog pos' do before { generate_dump_file(<?@[\\]^_{\|}~| } include_examples 'dump contains create table without records' end context 'when the column name includes a dot' do let(:col_name) { %q|my.column| } include_examples 'dump contains create table without records' end end context 'when dump contains create table with multi inserts and invalid utf8 byte sequences' do let(:dump_content) { <