text:
PYTHONIC_NS_BEGIN

namespace operator_
{
  bool truth(bool const &a);

  DEFINE_FUNCTOR(pythonic::operator_, truth);
}
PYTHONIC_NS_END

#endif


text:
import React from 'react'
import { shallow } from 'enzyme';
import FetchTodosError from '../FetchTodosError'

describe('FetchTodosError', () => {

  it('should render an error message', () => {
    const component = shallow(
      <FetchTodosError message="Error message" />
    );
    expect(component.find('p > i').text()).toEqual('Error message');
  });

  it('should call an external function when pressing the retry button', () => {
    const handler = jest.fn();
    const component = shallow(
      <FetchTodosError message="Error message" onRetry={handler} />
    );
    component.find('button').simulate('click', { preventDefault() {} });
    expect(handler).toHaveBeenCalled();
  })
})

redpajama_set_name: RedPajamaGithub


text:
package net.minecraft.block;

import java.util.Random;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyInteger;
import net.minecraft.block.state.BlockState;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.EnumDyeColor;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumWorldBlockLayer;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;

public class BlockCocoa extends BlockDirectional implements IGrowable
{
    public static final PropertyInteger field_176501_a = PropertyInteger.create("age", 0, 2);
    private static final String __OBFID = "CL_00000216";

    public BlockCocoa()
    {
        super(Material.plants);
        this.setDefaultState(this.blockState.getBaseState().withProperty(AGE, EnumFacing.NORTH).withProperty(field_176501_a, Integer.valueOf(0)));
        this.setTickRandomly(true);
    }

    public void updateTick(World worldIn, BlockPos pos, IBlockState state, Random rand)
    {
        if (!this.canBlockStay(worldIn, pos, state))
        {
            this.dropBlock(worldIn, pos, state);
        }
        else if (worldIn.rand.nextInt(5) == 0)
        {
            int var5 = ((Integer)state.getValue(field_176501_a)).intValue();

            if (var5 < 2)
            {
                worldIn.setBlockState(pos, state.withProperty(field_176501_a, Integer.valueOf(var5 + 1)), 2);
            }
        }
    }

    public boolean canBlockStay(World worldIn, BlockPos p_176499_2_, IBlockState p_176499_3_)
    {
        p_176499_2_ = p_176499_2_.offset((EnumFacing)p_176499_3_.getValue(AGE));
        IBlockState var4 = worldIn.getBlockState(p_176499_2_);
        return var4.getBlock() == Blocks.log && var4.getValue(BlockPlanks.VARIANT_PROP) == BlockPlanks.EnumType.JUNGLE;
    }

    public boolean isFullCube()
    {
        return false;
    }

    public boolean isOpaqueCube()
    {
        return false;
    }

    public AxisAlignedBB getCollisionBoundingBox(World worldIn, BlockPos pos, IBlockState state)
    {
        this.setBlockBoundsBasedOnState(worldIn, pos);
        return super.getCollisionBoundingBox(worldIn, pos, state);
    }

    public AxisAlignedBB getSelectedBoundingBox(World worldIn, BlockPos pos)
    {
        this.setBlockBoundsBasedOnState(worldIn, pos);
        return super.getSelectedBoundingBox(worldIn, pos);
    }

    public void setBlockBoundsBasedOnState(IBlockAccess access, BlockPos pos)
    {
        IBlockState var3 = access.getBlockState(pos);
        EnumFacing var4 = (EnumFacing)var3.getValue(AGE);
        int var5 = ((Integer)var3.getValue(field_176501_a)).intValue();
        int var6 = 4 + var5 * 2;
        int var7 = 5 + var5 * 2;
        float var8 = (float)var6 / 2.0F;

        switch (BlockCocoa.SwitchEnumFacing.FACINGARRAY[var4.ordinal()])
        {
            case 1:
                this.setBlockBounds((8.0F - var8) / 16.0F, (12.0F - (float)var7) / 16.0F, (15.0F - (float)var6) / 16.0F, (8.0F + var8) / 16.0F, 0.75F, 0.9375F);
                break;

            case 2:
                this.setBlockBounds((8.0F - var8) / 16.0F, (12.0F - (float)var7) / 16.0F, 0.0625F, (8.0F + var8) / 16.0F, 0.75F, (1.0F + (float)var6) / 16.0F);
                break;

            case 3:
                this.setBlockBounds(0.0625F, (12.0F - (float)var7) / 16.0F, (8.0F - var8) / 16.0F, (1.0F + (float)var6) / 16.0F, 0.75F, (8.0F + var8) / 16.0F);
                break;

            case 4:
                this.setBlockBounds((15.0F - (float)var6) / 16.0F, (12.0F - (float)var7) / 16.0F, (8.0F - var8) / 16.0F, 0.9375F, 0.75F, (8.0F + var8) / 16.0F);
        }
    }

    public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
    {
        EnumFacing var6 = EnumFacing.fromAngle((double)placer.rotationYaw);
        worldIn.setBlockState(pos, state.withProperty(AGE, var6), 2);
    }

    public IBlockState onBlockPlaced(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
    {
        if (!facing.getAxis().isHorizontal())
        {
            facing = EnumFacing.NORTH;
        }

        return this.getDefaultState().withProperty(AGE, facing.getOpposite()).withProperty(field_176501_a, Integer.valueOf(0));
    }

    public void onNeighborBlockChange(World worldIn, BlockPos pos, IBlockState state, Block neighborBlock)
    {
        if (!this.canBlockStay(worldIn, pos, state))
        {
            this.dropBlock(worldIn, pos, state);
        }
    }

    private void dropBlock(World worldIn, BlockPos p_176500_2_, IBlockState p_176500_3_)
    {
        worldIn.setBlockState(p_176500_2_, Blocks.air.getDefaultState(), 3);
        this.dropBlockAsItem(worldIn, p_176500_2_, p_176500_3_, 0);
    }

    /**
     * Spawns this Block's drops into the World as EntityItems.
     *
     * @param chance The chance that each Item is actually spawned (1.0 = always, 0.0 = never)
     * @param fortune The player's fortune level
     */
    public void dropBlockAsItemWithChance(World worldIn, BlockPos pos, IBlockState state, float chance, int fortune)
    {
        int var6 = ((Integer)state.getValue(field_176501_a)).intValue();
        byte var7 = 1;

        if (var6 >= 2)
        {
            var7 = 3;
        }

        for (int var8 = 0; var8 < var7; ++var8)
        {
            spawnAsEntity(worldIn, pos, new ItemStack(Items.dye, 1, EnumDyeColor.BROWN.getDyeColorDamage()));
        }
    }

    public Item getItem(World worldIn, BlockPos pos)
    {
        return Items.dye;
    }

    public int getDamageValue(World worldIn, BlockPos pos)
    {
        return EnumDyeColor.BROWN.getDyeColorDamage();
    }

    public boolean isStillGrowing(World worldIn, BlockPos p_176473_2_, IBlockState p_176473_3_, boolean p_176473_4_)
    {
        return ((Integer)p_176473_3_.getValue(field_176501_a)).intValue() < 2;
    }

    public boolean canUseBonemeal(World worldIn, Random p_180670_2_, BlockPos p_180670_3_, IBlockState p_180670_4_)
    {
        return true;
    }

    public void grow(World worldIn, Random p_176474_2_, BlockPos p_176474_3_, IBlockState p_176474_4_)
    {
        worldIn.setBlockState(p_176474_3_, p_176474_4_.withProperty(field_176501_a, Integer.valueOf(((Integer)p_176474_4_.getValue(field_176501_a)).intValue() + 1)), 2);
    }

    public EnumWorldBlockLayer getBlockLayer()
    {
        return EnumWorldBlockLayer.CUTOUT;
    }

    /**
     * Convert the given metadata into a BlockState for this Block
     */
    public IBlockState getStateFromMeta(int meta)
    {
        return this.getDefaultState().withProperty(AGE, EnumFacing.getHorizontal(meta)).withProperty(field_176501_a, Integer.valueOf((meta & 15) >> 2));
    }

    /**
     * Convert the BlockState into the correct metadata value
     */
    public int getMetaFromState(IBlockState state)
    {
        byte var2 = 0;
        int var3 = var2 | ((EnumFacing)state.getValue(AGE)).getHorizontalIndex();
        var3 |= ((Integer)state.getValue(field_176501_a)).intValue() << 2;
        return var3;
    }

    protected BlockState createBlockState()
    {
        return new BlockState(this, new IProperty[] {AGE, field_176501_a});
    }

    static final class SwitchEnumFacing
    {
        static final int[] FACINGARRAY = new int[EnumFacing.values().length];
        private static final String __OBFID = "CL_00002130";

        static
        {
            try
            {
                FACINGARRAY[EnumFacing.SOUTH.ordinal()] = 1;
            }
            catch (NoSuchFieldError var4)
            {
                ;
            }

            try
            {
                FACINGARRAY[EnumFacing.NORTH.ordinal()] = 2;
            }
            catch (NoSuchFieldError var3)
            {
                ;
            }

            try
            {
                FACINGARRAY[EnumFacing.WEST.ordinal()] = 3;
            }
            catch (NoSuchFieldError var2)
            {
                ;
            }

            try
            {
                FACINGARRAY[EnumFacing.EAST.ordinal()] = 4;
            }
            catch (NoSuchFieldError var1)
            {
                ;
            }
        }
    }
}


text:
<!doctype html>

		<title>Demo page</title>
		<meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
		<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"/>
		<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css"/>
		<link rel="stylesheet" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css"/>
		<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.5.1/katex.min.css">
		<link rel="stylesheet" href="https://raw.githubusercontent.com/ritz078/embed.js/master/src/embed.css"/>
		<link rel="stylesheet" href="/static/styles.css"/>


text:
package edu.uci.ics.jung.io.graphml.parser;

import javax.xml.stream.XMLEventReader;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

import edu.uci.ics.jung.graph.Hypergraph;
import edu.uci.ics.jung.io.GraphIOException;
import edu.uci.ics.jung.io.graphml.ExceptionConverter;

/**
 * Parses an element that just contains text.
 *
 * @author Nathan Mittler - nathan.mittler@gmail.com
 */
public class StringElementParser<G extends Hypergraph<V,E>,V,E> extends AbstractElementParser<G,V,E> {

    public StringElementParser(ParserContext<G,V,E> parserContext) {
        super(parserContext);
    }

    public String parse(XMLEventReader xmlEventReader, StartElement start)
            throws GraphIOException {

        try {
            String str = null;

            while (xmlEventReader.hasNext()) {

                XMLEvent event = xmlEventReader.nextEvent();
                if (event.isStartElement()) {

                    // Parse the unknown element.
                    getUnknownParser().parse(xmlEventReader, event
                            .asStartElement());
                } else if (event.isEndElement()) {
                    EndElement end = (EndElement) event;
                    verifyMatch(start, end);
                    break;
                } else if (event.isCharacters()) {
                    Characters characters = (Characters) event;
                    str = characters.getData();
                }
            }

            return str;

        } catch (Exception e) {
            ExceptionConverter.convert(e);
        }

        return null;
    }
}


text:
print("{foo}".format(**dict({'foo': 'bar'})))
<warning descr="Too few arguments for format string">"{}"</warning>.format()


text:
<!DOCTYPE html>

  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
  <link rel="stylesheet" href="test.css">
  <title>Paginate unit tests</title>

Paginate unit tests

    Running… see browser console for results

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17


text:
package pl.java.scalatech.generator;

import pl.java.scalatech.domain.generator.TableGeneratorEntity;

public class TableGeneratorTest extends AbstractGeneratorTest {

    @Override
    String getEntityName() {
        return TableGeneratorEntity.class.getSimpleName();
    }

    @Override
    Object createEntity(int i) {
        return new TableGeneratorEntity("gen_"+i);
    }

}


text:
package org.springframework.boot.convert;

import java.util.function.Consumer;
import java.util.stream.Stream;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;

import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
import org.springframework.format.Formatter;
import org.springframework.format.support.FormattingConversionService;

/**
 * Factory for creating a {@link Stream stream} of {@link Arguments} for use in a
 * {@link ParameterizedTest parameterized test}.
 *
 * @author Phillip Webb
 * @author Andy Wilkinson
 */
final class ConversionServiceArguments {

	private ConversionServiceArguments() {
	}

	static Stream<? extends Arguments> with(Formatter<?> formatter) {
		return with((conversionService) -> conversionService.addFormatter(formatter));
	}

	static Stream<? extends Arguments> with(GenericConverter converter) {
		return with((conversionService) -> conversionService.addConverter(converter));
	}

	static Stream<? extends Arguments> with(Consumer<FormattingConversionService> initializer) {
		FormattingConversionService withoutDefaults = new FormattingConversionService();
		initializer.accept(withoutDefaults);
		return Stream.of(
				Arguments.of(new NamedConversionService(withoutDefaults, "Without defaults conversion service")),
				Arguments.of(new NamedConversionService(new ApplicationConversionService(),
						"Application conversion service")));
	}

	static boolean isApplicationConversionService(ConversionService conversionService) {
		if (conversionService instanceof NamedConversionService namedConversionService) {
			return isApplicationConversionService(namedConversionService.delegate);
		}
		return conversionService instanceof ApplicationConversionService;
	}

	static class NamedConversionService implements ConversionService {

		private final ConversionService delegate;

		private final String name;

		NamedConversionService(ConversionService delegate, String name) {
			this.delegate = delegate;
			this.name = name;
		}

		@Override
		public boolean canConvert(Class<?> sourceType, Class<?> targetType) {
			return this.delegate.canConvert(sourceType, targetType);
		}

		@Override
		public boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType) {
			return this.delegate.canConvert(sourceType, targetType);
		}

		@Override
		public <T> T convert(Object source, Class<T> targetType) {
			return this.delegate.convert(source, targetType);
		}

		@Override
		public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
			return this.delegate.convert(source, sourceType, targetType);
		}

		@Override
		public String toString() {
			return this.name;
		}

	}

}


text:
<?php

declare(strict_types=1);

namespace spec\FSi\Bundle\FormExtensionsBundle\Form\EventListener;

use FSi\Bundle\FormExtensionsBundle\Model\PositionableInterface;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;

class SortableCollectionListenerSpec extends ObjectBehavior
{
    public function it_is_event_subscriber()
    {
        $this->beAnInstanceOf(EventSubscriberInterface::class);
    }

    public function it_listen_to_events()
    {
        $this->getSubscribedEvents()->shouldReturn([
            FormEvents::PRE_SUBMIT => 'rememberItemPosition',
            FormEvents::SUBMIT => 'persistItemPosition',
        ]);
    }

    public function it_does_nothing_when_no_data(
        FormEvent $formEvent1,
        FormEvent $formEvent2,
        FormInterface $form,
        PositionableInterface $item0,
        PositionableInterface $item1,
        PositionableInterface $item2
    ) {
        $formEvent1->getForm()->willReturn($form);
        $formEvent1->getData()->willReturn(null);
        $this->rememberItemPosition($formEvent1);
        $formEvent2->getForm()->willReturn($form);
        $formEvent2->getData()->willReturn([$item0, $item1, $item2]);
        $item0->setPosition(Argument::any())->shouldNotBeCalled();
        $item1->setPosition(Argument::any())->shouldNotBeCalled();
        $item2->setPosition(Argument::any())->shouldNotBeCalled();
        $this->persistItemPosition($formEvent2);
    }

    public function it_does_nothing_when_empty_array(
        FormEvent $formEvent1,
        FormEvent $formEvent2,
        FormInterface $form,
        PositionableInterface $item0,
        PositionableInterface $item1,
        PositionableInterface $item2
    ) {
        $formEvent1->getForm()->willReturn($form);
        $formEvent1->getData()->willReturn([]);
        $this->rememberItemPosition($formEvent1);
        $formEvent2->getForm()->willReturn($form);
        $formEvent2->getData()->willReturn([$item0, $item1, $item2]);
        $item0->setPosition(Argument::any())->shouldNotBeCalled();
        $item1->setPosition(Argument::any())->shouldNotBeCalled();
        $item2->setPosition(Argument::any())->shouldNotBeCalled();
        $this->persistItemPosition($formEvent2);
    }

    public function it_sets_positions(
        FormEvent $formEvent1,
        FormEvent $formEvent2,
        FormInterface $form,
        PositionableInterface $item0,
        PositionableInterface $item1,
        PositionableInterface $item2
    ) {
        $formEvent1->getForm()->willReturn($form);
        $formEvent1->getData()->willReturn([0 => '', 2 => '', 1 => '']);
        $this->rememberItemPosition($formEvent1);
        $formEvent2->getForm()->willReturn($form);
        $formEvent2->getData()->willReturn([$item0, $item1, $item2]);
        $item0->setPosition(1)->shouldBeCalled();
        $item1->setPosition(3)->shouldBeCalled();
        $item2->setPosition(2)->shouldBeCalled();
        $this->persistItemPosition($formEvent2);
    }

    public function is_set_positions_even_when_elements_are_removed(
        FormEvent $formEvent1,
        FormEvent $formEvent2,
        FormInterface $form,
        PositionableInterface $item0,
        PositionableInterface $item1,
        PositionableInterface $item2
    ) {
        $formEvent1->getForm()->willReturn($form);
        $formEvent1->getData()->willReturn([0 => '', 1 => '', 2 => '']);
        $this->rememberItemPosition($formEvent1);
        $formEvent2->getForm()->willReturn($form);
        $formEvent2->getData()->willReturn([$item0, $item2]);
        $item0->setPosition(1)->shouldBeCalled();
        $item1->setPosition(Argument::any())->shouldNotBeCalled();
        $item2->setPosition(2)->shouldBeCalled();
        $this->persistItemPosition($formEvent2);
    }

    public function it_sets_positions_for_two_collections_in_the_same_request(
        FormEvent $form1Event1,
        FormEvent $form1Event2,
        FormInterface $form1,
        PositionableInterface $collection1Item0,
        PositionableInterface $collection1Item1,
        PositionableInterface $collection1Item2,
        FormEvent $form2Event1,
        FormEvent $form2Event2,
        FormInterface $form2,
        PositionableInterface $collection2Item0,
        PositionableInterface $collection2Item1,
        PositionableInterface $collection2Item2
    ) {
        $form1Event1->getForm()->willReturn($form1);
        $form1Event1->getData()->willReturn([0 => '', 2 => '', 1 => '']);
        $this->rememberItemPosition($form1Event1);

        $form2Event1->getForm()->willReturn($form2);
        $form2Event1->getData()->willReturn([1 => '', 0 => '', 2 => '']);
        $this->rememberItemPosition($form2Event1);

        $form1Event2->getForm()->willReturn($form1);
        $form1Event2->getData()->willReturn([$collection1Item0, $collection1Item1, $collection1Item2]);
        $collection1Item0->setPosition(1)->shouldBeCalled();
        $collection1Item1->setPosition(3)->shouldBeCalled();
        $collection1Item2->setPosition(2)->shouldBeCalled();
        $this->persistItemPosition($form1Event2);

        $form2Event2->getForm()->willReturn($form2);
        $form2Event2->getData()->willReturn([$collection2Item0, $collection2Item1, $collection2Item2]);
        $collection2Item0->setPosition(2)->shouldBeCalled();
        $collection2Item1->setPosition(1)->shouldBeCalled();
        $collection2Item2->setPosition(3)->shouldBeCalled();
        $this->persistItemPosition($form2Event2);
    }
}


text:
<!DOCTYPE html>

    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />

<title>protobuf基本使用 | 落风的博客</title>
<meta name="author" content="落风">

  <meta name="keywords" content="protobuf">

<link rel="shortcut icon" href="http://7xpui7.com1.z0.glb.clouddn.com/blog-site-favicon.ico" />

<link rel="stylesheet" type="text/css" href="/assets/css/style.css">

<link href="/pages/rss.xml" rel="alternate" title="落风的博客" type="application/atom+xml">

全部

Java

Android

NDK

其他

HTML5

工程相关

网络技术

数据处理

VideoAndMap

    <form action="" id="search-form">

      <input id="search-input" type="text" placeholder="Search...">
    </form>

      jar打包问题Apr 2018

      http请求头Apr 2018

      Fiddler抓取数据失败:tunnel to 443Apr 2018

      线程实例分析Apr 2018

      JNI常见问题(问题查询笔记)2Mar 2018

      DCloud下的静态资源路径Mar 2018

      python4-mxnet笔记Mar 2018

      Android增量更新Mar 2018

      Android优化Mar 2018

      Android访问存储目录Mar 2018

      PHP语法简要笔记Jan 2018

      PHP开发环境搭建Jan 2018

      PHP开发环境搭建Jan 2018

      AndroidHTTPS安全请求解析2-手机请求以及连接捕获Jan 2018

      Android HTTPS安全请求解析-keystore工具的使用Jan 2018

      混淆点义Oct 2017

      oracle数据库入门Sep 2017

      Google离线地图Sep 2017

      GPS坐标区域判定2Sep 2017

      GPS坐标区域判定1Sep 2017

      PHP开发环境搭建Sep 2017

      线程实例分析Sep 2017

      线程复习笔记Sep 2017

      android权限管理Aug 2017

      maven2Jul 2017

      数据库测试Jul 2017

      cordovaJul 2017

      Kotlin笔记Jun 2017

      python笔记2May 2017

      Retrofit浅析-OkHttp-rxjavaMay 2017

      python笔记1Apr 2017

      Freemarker基本使用Apr 2017

      GIT配置Apr 2017

      Android反编译smali文件的修改Mar 2017

      BootstrapMar 2017

      android反编译还原项目指南Mar 2017

      一些web相关东西(摘自网络)Mar 2017

      linux网络调试Mar 2017

      如何将已存在的APK项目作为资源引用Mar 2017

      protobuf基本使用Mar 2017

      dockerMar 2017

      网络探测技术初探Mar 2017

      GBK编码问题Feb 2017

      eclipse配合maven导入项目遇到的问题Jan 2017

      FastDFS配置文档Jan 2017

      intellij尝试Dec 2016

      MAVEN配置Dec 2016

      flash RTMP 推流Dec 2016

      JBMP安装Dec 2016

      c++学习笔记Dec 2016

      c语言微知识点Nov 2016

      jni编程中C++/C语言一些问题Nov 2016

      RTMP延时问题Nov 2016

      ffmpeg/ffplay命令记录(转载,整理)Nov 2016

      Android数据库并发操作Nov 2016

      SDL&androidNov 2016

      live555初探-修改live555当前工作目录Oct 2016

      live555 window下编译运行以及Android平台的移植Oct 2016

      red5流媒体服务器的搭建以及Tomcat上的集成Oct 2016

      Android手机视频直播推流-RTMP推流-解决方案一Oct 2016

      基于Android的手机推流Oct 2016

      音视频编解码-ffmpeg解码Oct 2016

      荒原日记-时空狂想Oct 2016

      Androidstudio解决javah生成头文件时找不到类的问题Sep 2016

      网络工程-抓包分析Sep 2016

      Android基站定位Sep 2016

      netty pointAug 2016

      netty框架是如何执行connect连接的Aug 2016

      netty自带心跳响应Aug 2016

      android svg动画Aug 2016

      AndroidStudio版本更新记录Aug 2016

      Androidstudio下的代码混淆Aug 2016

      nine patch图片的用法绘制以及作用Aug 2016

      Android解压缩zip文件Jul 2016

      程序员编程语录Jun 2016

      Android数据库和Bean的交互Apr 2016

      荒原日记-习惯Apr 2016

      荒原日记-开篇Apr 2016

      Visual Studio开发Android程序Feb 2016

      C++学习整理Feb 2016

      Socket编程笔记Feb 2016

      git常用命令行Feb 2016

      android反编译Feb 2016

      html5内嵌入androidFeb 2016

      HTML5绘图学习记录Feb 2016

      HTML5绘图学习Feb 2016

      想要冬眠的狐狸Jan 2016

      擅长卖萌的狐狸Jan 2016

      正在找东西的狐狸Jan 2016

      我对瀑布开发模式和敏捷开发模式的理解Jan 2016

      梦花Jan 2016

      Android滤镜-快速模糊Jan 2016

      listview焦点冲突Jan 2016

      NumberPicker与StringPickerJan 2016

      Androidstudio下jni的一些问题Jan 2016

      Android绘图-LOGO兼容低版本Jan 2016

      Android绘图-LOGO-实现3Jan 2016

      Android绘图-LOGO-实现2Jan 2016

      Android绘图-LOGO-实现1Jan 2016

      android图像处理:像素过滤Jan 2016

protobuf基本使用

文章链接:http://www.liuschen.com

下载protobuf,安装都是很简单的步骤,如果想要将安装文件安装到特定目录,需要在configure的时候加入具体的路径参数

./configure --prefix=/home/myprotobuf(自己指定的路径)

使用:

为了方便可以先将目录加入环境变量(这个是临时的):

exprot PATH=/home/myprotobuf/bin/:$PATH

将动态连接库的搜索路径加入到系统中(之后编译链接代码时会用到):

export LD_LIBRARY_PATH=/home/myprotobuf/lib:$LD_LIBRARY_PATH

首先,建一个文件protobuf_demo.proto,通过命令生成cc文件和头文件

protoc --cpp_out=. ./protobuf_demo.proto

protobuf_demo.proto记录了目标文件需要配置的元素

message protobuf_demo{

required int32 id = 1;
required string str = 2;
required string hello = 4;

}

然后再编写cpp文件并在文件中引用上面生成的C++头文件,我的文件如下

#include "protobuf_demo.pb.h"
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/text_format.h>

#include <iostream>
#include <fcntl.h>

using namespace std;
using google::protobuf::io::FileInputStream;
using google::protobuf::io::FileOutputStream;
using google::protobuf::io::ZeroCopyInputStream;
using google::protobuf::io::CodedInputStream;
using google::protobuf::io::ZeroCopyOutputStream;
using google::protobuf::io::CodedOutputStream;

int main(void)
{
protobuf_demo msg;
const char * filename = "some.prototxt";
int fd = open(filename,O_RDONLY);
if(fd == -1)
{
  cout << "File not found:" << filename << endl;
}
FileInputStream* input = new FileInputStream(fd);
bool success = google::protobuf::TextFormat::Parse(input,&msg);

cout << msg.id() << endl;
cout << msg.str() << endl;
cout << msg.hello() << endl;

}

编译生成可执行文件,然后通过该文件就可以读出当前文件加下some.prototxt的值

id: 1888
str: "192.168.0.1
hello: "haha"

  Please enable JavaScript to view the comments powered by Disqus.
  Loading Disqus comments...

Powered by Jekyll  |  Theme 3-Jekyll  |  Hosted on Github

          Table of Contents

    <button id="js-fullscreen"></button>


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<TITLE>
CacheConfigType
</TITLE>

<META NAME="date" CONTENT="2011-07-19">

<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../../../../stylesheet.css" TITLE="Style">

      Overview
      Package
    Class
      Use
      Tree
      Deprecated
      Index
      Help

 PREV CLASS
 NEXT CLASS

  FRAMES
 NO FRAMES

  All Classes

  SUMMARY: NESTED | FIELD | CONSTR | METHOD

DETAIL: FIELD | CONSTR | METHOD

org.jboss.shrinkwrap.descriptor.api.jboss51

Interface CacheConfigType<T>

All Superinterfaces:
org.jboss.shrinkwrap.descriptor.api.Child<T>

All Known Implementing Classes:
CacheConfigTypeImpl

public interface CacheConfigType<T>
extends org.jboss.shrinkwrap.descriptor.api.Child<T>

This interface defines the contract for the  cache-configType  xsd type

 Original Documentation:

 Element for specifying the class used to provide the caching mechanism for a bean,

 and the cache parameters

Since:

Generation date :2011-07-19T22:54:35.59+02:00

Author:

Ralf Battenfeld

Method Summary

 java.lang.Integer
getCacheMaxSize()

          Returns the cache-max-size element

 java.lang.String
getCacheName()

          Returns the cache-name element

 java.lang.String
getCacheValue()

          Returns the cache-value element

 java.lang.Integer
getIdleTimeoutSeconds()

          Returns the idle-timeout-seconds element

 java.lang.String
getPersistenceManager()

          Returns the persistence-manager element

 java.lang.Integer
getRemoveTimeoutSeconds()

          Returns the remove-timeout-seconds element

 java.lang.String
getReplicationIsPassivation()

          Returns the replication-is-passivation element

 CacheConfigType<T>
removeCacheMaxSize()

          Removes the cache-max-size element

 CacheConfigType<T>
removeCacheName()

          Removes the cache-name element

 CacheConfigType<T>
removeCacheValue()

          Removes the cache-value element

 CacheConfigType<T>
removeIdleTimeoutSeconds()

          Removes the idle-timeout-seconds element

 CacheConfigType<T>
removePersistenceManager()

          Removes the persistence-manager element

 CacheConfigType<T>
removeRemoveTimeoutSeconds()

          Removes the remove-timeout-seconds element

 CacheConfigType<T>
removeReplicationIsPassivation()

          Removes the replication-is-passivation element

 CacheConfigType<T>
setCacheMaxSize(java.lang.Integer cacheMaxSize)

          If not already created, a new cache-max-size element with the given value will be created.

 CacheConfigType<T>
setCacheName(java.lang.String cacheName)

          If not already created, a new cache-name element with the given value will be created.

 CacheConfigType<T>
setCacheValue(java.lang.String cacheValue)

          If not already created, a new cache-value element with the given value will be created.

 CacheConfigType<T>
setIdleTimeoutSeconds(java.lang.Integer idleTimeoutSeconds)

          If not already created, a new idle-timeout-seconds element with the given value will be created.

 CacheConfigType<T>
setPersistenceManager(java.lang.String persistenceManager)

          If not already created, a new persistence-manager element with the given value will be created.

 CacheConfigType<T>
setRemoveTimeoutSeconds(java.lang.Integer removeTimeoutSeconds)

          If not already created, a new remove-timeout-seconds element with the given value will be created.

 CacheConfigType<T>
setReplicationIsPassivation(java.lang.String replicationIsPassivation)

          If not already created, a new replication-is-passivation element with the given value will be created.

Methods inherited from interface org.jboss.shrinkwrap.descriptor.api.Child

up

Method Detail

setCacheValue

CacheConfigType<T> setCacheValue(java.lang.String cacheValue)

If not already created, a new cache-value element with the given value will be created.
 Otherwise, the existing cache-value element will be updated with the given value.

Returns:
the current instance of CacheConfigType<T>

removeCacheValue

CacheConfigType<T> removeCacheValue()

Removes the cache-value element

Returns:
the current instance of CacheConfigType<T>

getCacheValue

java.lang.String getCacheValue()

Returns the cache-value element

Returns:
the node defined for the element cache-value

setCacheMaxSize

CacheConfigType<T> setCacheMaxSize(java.lang.Integer cacheMaxSize)

If not already created, a new cache-max-size element with the given value will be created.
 Otherwise, the existing cache-max-size element will be updated with the given value.

Returns:
the current instance of CacheConfigType<T>

removeCacheMaxSize

CacheConfigType<T> removeCacheMaxSize()

Removes the cache-max-size element

Returns:
the current instance of CacheConfigType<T>

getCacheMaxSize

java.lang.Integer getCacheMaxSize()

Returns the cache-max-size element

Returns:
the node defined for the element cache-max-size

setIdleTimeoutSeconds

CacheConfigType<T> setIdleTimeoutSeconds(java.lang.Integer idleTimeoutSeconds)

If not already created, a new idle-timeout-seconds element with the given value will be created.
 Otherwise, the existing idle-timeout-seconds element will be updated with the given value.

Returns:
the current instance of CacheConfigType<T>

removeIdleTimeoutSeconds

CacheConfigType<T> removeIdleTimeoutSeconds()

Removes the idle-timeout-seconds element

Returns:
the current instance of CacheConfigType<T>

getIdleTimeoutSeconds

java.lang.Integer getIdleTimeoutSeconds()

Returns the idle-timeout-seconds element

Returns:
the node defined for the element idle-timeout-seconds

setRemoveTimeoutSeconds

CacheConfigType<T> setRemoveTimeoutSeconds(java.lang.Integer removeTimeoutSeconds)

If not already created, a new remove-timeout-seconds element with the given value will be created.
 Otherwise, the existing remove-timeout-seconds element will be updated with the given value.

Returns:
the current instance of CacheConfigType<T>

removeRemoveTimeoutSeconds

CacheConfigType<T> removeRemoveTimeoutSeconds()

Removes the remove-timeout-seconds element

Returns:
the current instance of CacheConfigType<T>

getRemoveTimeoutSeconds

java.lang.Integer getRemoveTimeoutSeconds()

Returns the remove-timeout-seconds element

Returns:
the node defined for the element remove-timeout-seconds

setCacheName

CacheConfigType<T> setCacheName(java.lang.String cacheName)

If not already created, a new cache-name element with the given value will be created.
 Otherwise, the existing cache-name element will be updated with the given value.

Returns:
the current instance of CacheConfigType<T>

removeCacheName

CacheConfigType<T> removeCacheName()

Removes the cache-name element

Returns:
the current instance of CacheConfigType<T>

getCacheName

java.lang.String getCacheName()

Returns the cache-name element

Returns:
the node defined for the element cache-name

setPersistenceManager

CacheConfigType<T> setPersistenceManager(java.lang.String persistenceManager)

If not already created, a new persistence-manager element with the given value will be created.
 Otherwise, the existing persistence-manager element will be updated with the given value.

Returns:
the current instance of CacheConfigType<T>

removePersistenceManager

CacheConfigType<T> removePersistenceManager()

Removes the persistence-manager element

Returns:
the current instance of CacheConfigType<T>

getPersistenceManager

java.lang.String getPersistenceManager()

Returns the persistence-manager element

Returns:
the node defined for the element persistence-manager

setReplicationIsPassivation

CacheConfigType<T> setReplicationIsPassivation(java.lang.String replicationIsPassivation)

If not already created, a new replication-is-passivation element with the given value will be created.
 Otherwise, the existing replication-is-passivation element will be updated with the given value.

Returns:
the current instance of CacheConfigType<T>

removeReplicationIsPassivation

CacheConfigType<T> removeReplicationIsPassivation()

Removes the replication-is-passivation element

Returns:
the current instance of CacheConfigType<T>

getReplicationIsPassivation

java.lang.String getReplicationIsPassivation()

Returns the replication-is-passivation element

Returns:
the node defined for the element replication-is-passivation

      Overview
      Package
    Class
      Use
      Tree
      Deprecated
      Index
      Help

 PREV CLASS
 NEXT CLASS

  FRAMES
 NO FRAMES

  All Classes

  SUMMARY: NESTED | FIELD | CONSTR | METHOD

DETAIL: FIELD | CONSTR | METHOD


text:
from itertools import chain
from collections import Counter

from packaging import version
from datetime import datetime
from dateutil.tz import tzlocal
import six
import scrapy
from scrapy.exporters import XmlItemExporter

from .items import RssItem
from .utils import format_rfc822
from .exceptions import *
from . import meta

class RssItemExporter(XmlItemExporter):
    def __init__(self, file, channel_title, channel_link, channel_description,
                 namespaces=None, item_cls=None,
                 language=None, copyright=None, managing_editor=None, webmaster=None,
                 pubdate=None, last_build_date=None, category=None, generator=None,
                 docs=None, ttl=None,
                 **kwargs):
        """
        RSS parameters semantics: https://validator.w3.org/feed/docs/rss2.html

        Parameters
        ----------
        namespaces : {str or None : str} or tuple of (str or None, str) or list of (str or None, str) or None
            predefined XML namespaces {prefix: URI, ...} or [(prefix, URI), ...]
        item_cls : type
            main class of RSS items (default: RssItem)

        Item fields that corresponds to RSS element with attributes or sub-elements,
        must be a dictionary-like such as
        {"attribute-name": "attribute-value"} (with special key "content" if RSS element must have content)
        or {"sub-element-name": "sub-element-content"}

        For example, the dictionary for <guid> element:
            >>> {'isPermalink': 'False', 'content': '0123456789abcdef'}
            that converts into
            <guid isPermalink="False">0123456789abcdef</guid>
        """
        kwargs['root_element'] = 'rss'
        kwargs['item_element'] = 'item'
        super(RssItemExporter, self).__init__(file, **kwargs)

        self.channel_element = 'channel'

        self.channel_title = channel_title
        self.channel_link = channel_link
        self.channel_description = channel_description

        self.channel_language = language
        self.channel_copyright = copyright
        if managing_editor and '@' not in managing_editor:
            raise ValueError('managing_editor field must contain at least e-mail. Passed: {}'.format(managing_editor))
        self.channel_managing_editor = managing_editor
        if webmaster and '@' not in webmaster:
            raise ValueError('webmaster field must contain at least e-mail. Passed: {}'.format(webmaster))
        self.channel_webmaster = webmaster
        self.channel_pubdate = pubdate
        self.channel_last_build_date = last_build_date if last_build_date \
            else datetime.today().replace(tzinfo=tzlocal())
        self.channel_category = ([category] if category and isinstance(category, six.string_types)
                                 and not isinstance(category, (list, set, tuple))
                                 else category)
        self.channel_generator = generator if generator is not None else 'Scrapy {}'.format(scrapy.__version__)
        self.channel_docs = docs
        self.channel_ttl = ttl

        if not item_cls:
            item_cls = RssItem
        elif not issubclass(item_cls, RssItem):
            raise ValueError('Item class must be RssItem class or its subclass')
        self._item_cls = item_cls

        if not namespaces:
            namespaces = {}
        elif isinstance(namespaces, (list, tuple)):
            namespaces = dict(namespaces)
        namespaces_iter = namespaces.items() if isinstance(namespaces, dict) else namespaces
        item_cls_namespaces = item_cls().get_namespaces(False)
        self._namespaces = {}
        skipped_ns_prefixes = set()
        for ns_prefix, ns_uri in chain(namespaces_iter, item_cls_namespaces):
            if ns_prefix in skipped_ns_prefixes:
                continue
            if ns_prefix in self._namespaces and ns_uri != self._namespaces[ns_prefix]:
                self._namespaces.pop(ns_prefix)
                skipped_ns_prefixes.add(ns_prefix)
            else:
                self._namespaces[ns_prefix] = ns_uri

    if version.parse(scrapy.__version__) < version.parse('1.4.0'):
        def _export_xml_field(self, name, serialized_value, depth):
            return super(RssItemExporter, self)._export_xml_field(name, serialized_value)

    def start_exporting(self):
        self.xg.startDocument()
        for ns_prefix, ns_uri in self._namespaces.items():
            self.xg.startPrefixMapping(ns_prefix, ns_uri)
        root_attrs = {(None, 'version'): '2.0'}
        self.xg.startElementNS((None, self.root_element), self.root_element, root_attrs)
        self.xg.startElement(self.channel_element, {})

        self._export_xml_field('title', self.channel_title, 1)
        self._export_xml_field('link', self.channel_link, 1)
        self._export_xml_field('description', self.channel_description, 1)
        if self.channel_language:
            self._export_xml_field('language', self.channel_language, 1)
        if self.channel_copyright:
            self._export_xml_field('copyright', self.channel_copyright, 1)
        if self.channel_managing_editor:
            self._export_xml_field('managingEditor', self.channel_managing_editor, 1)
        if self.channel_webmaster:
            self._export_xml_field('webMaster', self.channel_webmaster, 1)
        if self.channel_pubdate:
            self._export_xml_field('pubdate',
                                   format_rfc822(self.channel_pubdate)
                                   if isinstance(self.channel_pubdate, datetime)
                                   else self.channel_pubdate, 1)
        self._export_xml_field('lastBuildDate',
                               format_rfc822(self.channel_last_build_date)
                               if isinstance(self.channel_last_build_date, datetime)
                               else self.channel_last_build_date, 1)
        if self.channel_category:
            for category in self.channel_category:
                self._export_xml_field('category', category, 1)
        if self.channel_generator:
            self._export_xml_field('generator', self.channel_generator, 1)
        if self.channel_docs:
            self._export_xml_field('docs', self.channel_docs, 1)
        if self.channel_ttl:
            self._export_xml_field('ttl', self.channel_ttl, 1)

    def export_item(self, item):
        if not isinstance(item, RssItem) and not isinstance(getattr(item, 'rss', None), RssItem):
            raise InvalidRssItemError("Item must have 'rss' field of type 'RssItem'")
        if not isinstance(item, RssItem):
            item = item.rss

        item_namespaces = set()
        if item.__class__ is not self._item_cls:
            item_namespaces = item.get_namespaces()
            item_namespaces -= set(self._namespaces.items())
            ns_prefix_count = Counter(ns_prefix for ns_prefix, _ in item_namespaces)
            item_namespaces = {ns for ns in item_namespaces if ns_prefix_count[ns[0]] == 1}
        item_namespaces = dict(item_namespaces)

        for elem_ns_prefix, elem_ns_uri in item_namespaces.items():
            self.xg.startPrefixMapping(elem_ns_prefix, elem_ns_uri)
        self.xg.startElementNS((None, self.item_element), self.item_element, {})

        for elem_name, elem_descr in item.elements.items():
            elem_value = getattr(item, str(elem_name))
            if elem_value.assigned:
                elem_values = elem_value if isinstance(elem_value, meta.MultipleElements) else (elem_value,)
                for elem_value in elem_values:
                    if not elem_value.is_valid():
                        raise InvalidRssItemAttributesError(elem_name,
                                                            list(elem_value.required_attrs),
                                                            elem_value.content_arg)

                    attrs = elem_value.serialize()
                    content = attrs.pop(elem_descr.content_arg.xml_name, None) if elem_descr.content_arg else None
                    undeclared_elem_namespaces = {ns_prefix: ns_uri
                                                  for ns_prefix, ns_uri in elem_descr.get_namespaces()
                                                  if (ns_prefix not in self._namespaces
                                                      or self._namespaces[ns_prefix] != ns_uri)
                                                  and (ns_prefix not in item_namespaces
                                                       or item_namespaces[ns_prefix] != ns_uri)}
                    if elem_name.ns_prefix:
                        elem_qname = '{}:{}'.format(elem_name.ns_prefix, elem_name.name)
                    else:
                        elem_qname = elem_name.name
                    for ns_prefix, ns_uri in undeclared_elem_namespaces.items():
                        self.xg.startPrefixMapping(ns_prefix, ns_uri)
                    self.xg.startElementNS(elem_name.xml_name, elem_qname, attrs)
                    if content:
                        self.xg.characters(content)
                    self.xg.endElementNS(elem_name.xml_name, elem_qname)
                    for ns_prefix, ns_uri in undeclared_elem_namespaces.items():
                        self.xg.endPrefixMapping(ns_prefix)

        self.xg.endElementNS((None, self.item_element), self.item_element)
        for elem_ns_prefix in item_namespaces:
            self.xg.endPrefixMapping(elem_ns_prefix)

    def finish_exporting(self):
        self.xg.endElement(self.channel_element)
        self.xg.endElementNS((None, self.root_element), self.root_element)
        for ns_prefix, ns_uri in self._namespaces.items():
            self.xg.startPrefixMapping(ns_prefix, ns_uri)
        self.xg.endDocument()


text:
All URIs are relative to *https://localhost*

Method | HTTP request | Description
------------- | ------------- | -------------
[**getTeams**](TeamsApi.md#getTeams) | **GET** /{sport}/teams | List All Teams

# **getTeams**
> [InlineResponse20018] getTeams(sport)

List All Teams

### Example
```javascript
var RtsmunityPublicApiSdk = require('rtsmunity-public-api-sdk');

var apiInstance = new RtsmunityPublicApiSdk.TeamsApi();

var sport = "sport_example"; // String | Sport key

var callback = function(error, data, response) {
  if (error) {
    console.error(error);
  } else {
    console.log('API called successfully. Returned data: ' + data);
  }
};
apiInstance.getTeams(sport, callback);
```

### Parameters

Name | Type | Description  | Notes
------------- | ------------- | ------------- | -------------
 **sport** | **String**| Sport key |

### Return type

[**[InlineResponse20018]**](InlineResponse20018.md)

### Authorization

No authorization required

### HTTP request headers

 - **Content-Type**: Not defined
 - **Accept**: application/json; charset=utf-8


text:
Count distinct values/cardinalities using HyperLogLog algorithm.

For a quick read of the HyperLogLog algorithm please refer to https://research.neustar.biz/2012/10/25/sketch-of-the-day-hyperloglog-cornerstone-of-a-big-data-infrastructure/.

I am currently using this for continously counting distinct values, for example, in realtime events, every event contains a user or session id, and we want to count how many distinct users or sessions while processing the events. Keeping a huge list of id can be a solution, but it would run out of memory eventually. Using HLL is O(1) in both space and time complexity, I also added an incremental counter on top of the HLL one, but it turns out to be not much different.

Following is one of my test result (using 1M random numbers)
```
Base: 951667, HLL:951690, IHLL:951683. HLL Error: 0.002%. IHLL Error: 0.001%
HLL Error Range:[-0.181%,0.069%]
IHLL Error Range:[-0.125%,0.051%]
```

### Usage ###
```
var counter = require('distinct-value-counter');
var idCounter = counter(0.001); // Specify expected precision, default is 0.01
idCounter.add('a');
idCounter.add('b');
expect(idCounter.count()).equal.to(2);
```


text:
--Nullability

ALTER TABLE DirectMarketing.Opportunity
ALTER COLUMN OpportunityID int NOT NULL;
GO
ALTER TABLE DirectMarketing.Opportunity
ALTER COLUMN ProspectID int NOT NULL;
GO
ALTER TABLE DirectMarketing.Opportunity
ALTER COLUMN DateRaised datetime NOT NULL;
GO
ALTER TABLE DirectMarketing.Opportunity
ALTER COLUMN Likelihood tinyint NOT NULL;
GO
ALTER TABLE DirectMarketing.Opportunity
ALTER COLUMN Rating char(1) NOT NULL;
GO
ALTER TABLE DirectMarketing.Opportunity
ALTER COLUMN EstimatedClosingDate date NOT NULL;
GO
ALTER TABLE DirectMarketing.Opportunity
ALTER COLUMN EstimatedRevenue decimal(10,2) NOT NULL;
GO

--Primary Key

ALTER TABLE DirectMarketing.Opportunity
ADD CONSTRAINT PK_Opportunity PRIMARY KEY CLUSTERED (OpportunityID, ProspectID);
GO

--Default

ALTER TABLE DirectMarketing.Opportunity
ADD CONSTRAINT dfDateRaised
DEFAULT (SYSDATETIME()) FOR DateRaised;
GO

--Challenge 2

INSERT INTO [DirectMarketing].[Opportunity]
           ([OpportunityID]
           ,[ProspectID]
           ,[Likelihood]
           ,[Rating]
           ,[EstimatedClosingDate]
           ,[EstimatedRevenue])
     VALUES
           (1,1,8,'A','12/12/2013',123000.00)
GO


text:
<component name="libraryTable">
  <library name="org.json">
    <CLASSES>
      <root url="jar://$PROJECT_DIR$/libs/org.json.jar!/" />
    </CLASSES>
    <JAVADOC />
    <SOURCES />
  </library>
</component>


text:
> The developers' draft

The [comfort](https://github.com/kaelzhang/comfort) option configurations.

### exports.options `Object`

An object composed of `<key>: <configuration>`

See npm module, `clean` for details.


text:
Read <http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator>
and <http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray>
and other literature.

Don't use `instanceof`, and also not `typeof`.

## Usage

```javascript
var type = require('otw/src/type');

type({a: 4});    // 'object
type([1, 2, 3]); // 'array'
type(new Date);  // 'date'
type(/a-z/);     // 'regexp'
type(Math);      // 'math'
type(JSON);      // 'json'

type(new Number(4));      // 'number'
type(new String('abc'));  // 'string'
type(new Boolean(true));  // 'boolean'
type(new ReferenceError); // 'error'

(function() {console.log(type(arguments))})(); // 'arguments'
```


text:
The product tests make use of user visible interfaces (e.g. `presto-cli`)
to test Presto for correctness. The product tests complement the unit tests
because unlike the unit tests, they exercise the Presto codebase end-to-end.

To keep the execution of the product tests as lightweight as possible we
decided to use [Docker](http://www.docker.com/). The general execution
setup is as follows: a single Docker container runs Hadoop in pseudo-distributed
mode and Presto runs either in Docker container(s) (both pseudo-distributed
and distributed setups are possible) or manually from IntelliJ (for
debugging Presto). The tests run in a separate JVM and they can be started
using the scripts found in `presto-product-tests/bin`. The product
tests are run using the [Tempto](https://github.com/prestodb/tempto) harness.

Developers should consider writing product tests in addition to any unit tests
when making changes to user visible features. The product tests should also
be run after all code changes to ensure no existing functionality has been
broken.

## Requirements

*Running the Presto product tests requires at least 4GB of free memory*

### GNU/Linux
* [`docker >= 1.10`](https://docs.docker.com/installation/#installation)

    ```
    wget -qO- https://get.docker.com/ | sh
    ```

* [`docker-compose >= 1.60`](https://docs.docker.com/compose/install/)

    ```
    pip install docker-compose
    ```

### OS X (10.8 "Mountain Lion" or newer)

* [`VirtualBox >= 5.0`](https://www.virtualbox.org/wiki/Downloads)

The Docker daemon cannot run natively on OS X because it uses Linux-specific
kernel features. Instead, the Docker daemon runs in a Linux VM created by
the `docker-machine` binary. Docker containers run in the Linux VM and are
controlled by the `docker` client binary that runs natively on OS X.
Both `docker-machine` and `docker` are included in the `docker-toolbox`
package, which must be installed.

* [`docker-toolbox >= 1.10`](https://www.docker.com/products/docker-toolbox)

In addition to `docker-machine` and `docker`, the `docker-toolbox`
package also install `docker-compose`, which is a multi-container
orchestration Python utility. To gain access to these utilities, start the
pre-configured shell environment by double-clicking on the "Docker Quickstart
Terminal" icon located in ~/Applications/Docker. Note that all commands listed
in subsequent parts of this tutorial must be run within such a pre-configured
shell.

#### Setting up a Linux VM for Docker

The `docker-toolbox` installation creates a VirtualBox VM called `default`.
To run product-tests on the `default` VM, it must be re-configured to use
4GB of memory with the following commands:

```
docker-machine stop
vboxmanage modifyvm default --memory 4096
docker-machine start
```

Alternatively, if you do not want to use the `default` VM to run the
product tests, you can create a new VM with the commands below. Note that
the `default` VM will always be running when you start a new pre-configured
shell environment. Permanently removing or replacing the `default` VM
is beyond the scope of this tutorial.

* Create a VM called <machine>. This should be done only once and not
every time a pre-configured shell is started:

    ```
    docker-machine create -d virtualbox --virtualbox-memory 4096 <machine>
    ```

* After the new VM is created, the pre-configured shell environment must be
told to use the `<machine>` VM instead of the `default` VM to run Docker
containers. These commands must be run every time a new pre-configured
shell is started:

    ```
    docker-machine start <machine>
    eval $(docker-machine env <machine>)
    ```

Note that for every new VM, the docker images on the previous
VM will have to be re-downloaded when the product tests are kicked
off. To avoid this unnecessary re-download, do not create new
VMs often.

## Use the `docker-compose` wrappers

We're using [multiple compose files](https://docs.docker.com/compose/extends/#multiple-compose-files)
because of the number of overrides needed for different environments,
and deficiencies of `extends:` syntax (see the note
[here](https://docs.docker.com/compose/extends/#extending-services)).

To ease the pain of passing multiple `-f` arguments to `docker-compose`,
each environment has a `compose.sh` wrapper script. Thanks to it, instead of e.g.

`docker-compose -f ./docker-compose.yml -f ../common/standard.yml -f ../common/jdbc_db.yml [compose commands]`

one can simply write

`compose.sh [compose commands]`

## Running the product tests

The Presto product tests must be run explicitly because they do not run
as part of the Maven build like the unit tests do. Note that the product
tests cannot be run in parallel. This means that only one instance of a
test can be run at once in a given environment. To run all product
tests and exclude the `quarantine`, `big_query` and `profile_specific_tests`
groups run the following command:

```
./mvnw install -DskipTests
presto-product-tests/bin/run_on_docker.sh <profile> -x quarantine,big_query,profile_specific_tests
```

where [profile](#profile) is one of either:
- **multinode** - pseudo-distributed Hadoop installation running on a
 single Docker container and a distributed Presto installation running on
 multiple Docker containers. For multinode the default configuration is
 1 coordinator and 1 worker.
- **singlenode** - pseudo-distributed Hadoop installation running on a
 single Docker container and a single node installation of Presto also running
 on a single Docker container.
- **singlenode-hdfs-impersonation** - pseudo-distributed Hadoop installation
 running on a single Docker container and a single node installation of Presto
 also running on a single Docker container. Presto impersonates the user who
 is running the query when accessing HDFS.
- **singlenode-kerberos-hdfs-impersonation** - pseudo-distributed kerberized
 Hadoop installation running on a single Docker container and a single node
 installation of kerberized Presto also running on a single Docker container.
 This profile has Kerberos impersonation. Presto impersonates the user who
 is running the query when accessing HDFS.
- **singlenode-kerberos-hdfs-no-impersonation** - pseudo-distributed Hadoop
 installation running on a single Docker container and a single node
 installation of kerberized Presto also running on a single Docker container.
 This profile runs Kerberos without impersonation.

Please keep in mind that if you run tests on Hive of version not greater than 1.0.1, you should exclude test from `post_hive_1_0_1` group by passing the following flag to tempto: `-x post_hive_1_0_1`.
First version of Hive capable of running tests from `post_hive_1_0_1` group is Hive 1.1.0.

For more information on the various ways in which Presto can be configured to
interact with Kerberized Hive and Hadoop, please refer to the [Hive connector documentation](https://prestodb.io/docs/current/connector/hive.html).

The `run_on_docker.sh` script can also run individual product tests. Presto
product tests are either [Java based](https://github.com/prestodb/tempto#java-based-tests)
or [convention based](https://github.com/prestodb/tempto#convention-based-sql-query-tests)
and each type can be run individually with the following commands:

```
# Run single Java based test
presto-product-tests/bin/run_on_docker.sh <profile> -t com.facebook.presto.tests.functions.operators.Comparison.testLessThanOrEqualOperatorExists
# Run single convention based test
presto-product-tests/bin/run_on_docker.sh <profile> -t sql_tests.testcases.system.selectInformationSchemaTables
```

Tests belong to a single or possibly multiple groups. Java based tests are
tagged with groups in the `@Test` annotation and convention based tests have
group information in the first line of their test file. Instead of running
single tests, or all tests, users can also run one or more test groups.
This enables users to test features in a cross functional way. To run a
particular group, use the `-g` argument as shown:

```
# Run all tests in the string_functions and create_table groups
presto-product-tests/bin/run_on_docker.sh <profile> -g string_functions,create_tables
```

Some groups of tests can only be run with certain profiles. For example,
impersonation tests can only be run with profiles where
impersonation is enabled (`singlenode-hdfs-impersonation` and
`singlenode-kerberos-hdfs-impersonation`) and no impersonation tests can
only be run with profiles where impersonation is disabled (`singlenode`
and `singlenode-kerberos-hdfs-no-impersonation`). Tests that require
a specific profile to run are called profile specific tests. In addition
to their respective group, all such tests also belong to a parent group
called `profile_specific_tests`. To exclude such tests from a run
make sure to add the `profile_specific_tests` group to the list of
excluded groups. The examples below illustrate the above concepts:

```
# Run the HDFS impersonation tests, where <profile> is one of either
# singlenode-hdfs-impersonation or singlenode-kerberos-hdfs-impersonation
presto-product-tests/bin/run_on_docker.sh <profile> -g hdfs_impersonation
# Run the no HDFS impersonation tests, where <profile> is one of either
# singlenode or singlenode-kerberos-hdfs-no-impersonation
presto-product-tests/bin/run_on_docker.sh <profile> -g hdfs_no_impersonation
# Run all tests excluding all profile specific tests
presto-product-tests/bin/run_on_docker.sh <profile> -x quarantine,big_query,profile_specific_tests
where <profile> can be any one of the available profiles
```

For running Java based tests from IntelliJ see the section on
[Debugging Java based tests](#debugging-java-based-tests).

To interrupt a product test run, send a single `Ctrl-C` signal. The scripts
running the tests will gracefully shutdown all containers. Any follow up
`Ctrl-C` signals will interrupt the shutdown procedure and possibly leave
containers in an inconsistent state.

## Debugging the product tests

### Debugging Java based tests

[Java based tests](https://github.com/prestodb/tempto#java-based-tests)
can be run and debugged from IntelliJ like regular TestNG tests with the
setup outlined below:

1. Ensure all project artifacts are up to date:

    ```
    ./mvnw install -DskipTests
    ```

2. Start Hadoop in pseudo-distributed mode in a Docker container:

    ```
    presto-product-tests/conf/docker/singlenode/compose.sh up -d hadoop-master
    ```

    Tip: To display container logs run:

    ```
    presto-product-tests/conf/docker/singlenode/compose.sh logs
    ```

3. Add an IP-to-host mapping for the `hadoop-master` host in `/etc/hosts`.
The format of `/etc/hosts` entries is `<ip> <host>`:

    - On GNU/Linux add the following mapping: `<container ip> hadoop-master`.
    The container IP can be obtained by running:

        ```
        docker inspect $(presto-product-tests/conf/docker/singlenode/compose.sh ps -q hadoop-master) | grep -i IPAddress
        ```

    - On OS X add the following mapping: `<docker machine ip> hadoop-master`.
    Since Docker containers run inside a Linux VM, on OS X we map the VM IP to
    the `hadoop-master` hostname. To obtain the IP of the Linux VM run:

        ```
        docker-machine ip <machine>
        ```

4. [Create a run configuration in IntelliJ](https://www.jetbrains.com/help/idea/2016.1/creating-and-editing-run-debug-configurations.html)
with the following parameters:

    - Use classpath of module: `presto-main`
    - Main class: `com.facebook.presto.server.PrestoServer`
    - Working directory: `presto-product-tests/conf/presto`
    - VM options: `-ea -Xmx2G -Dconfig=etc/config.properties -Dlog.levels-file=etc/log.properties -DHADOOP_USER_NAME=hive -Duser.timezone=UTC`

5. Start the Presto server with the newly created run configuration.

6. In IntelliJ, right click on a test method name or test class to run
or debug the respective test(s).

7. Remember to stop the Hadoop container once debugging is done with the
following command:

    ```
    presto-product-tests/conf/docker/singlenode/compose.sh down
    ```

### Debugging convention based tests

Some of the product tests are implemented in a
[convention based](https://github.com/prestodb/tempto#convention-based-sql-query-tests)
manner. Such tests can not be run directly from IntelliJ and the following
steps explain how to debug convention based tests:

1. Follow steps [1-5] from the [Debugging Java based tests](#debugging-java-based-tests)
section.

2. Run a convention based test with the following JVM debug flags:

    ```
    PRODUCT_TESTS_JVM_OPTIONS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=<debug port>" presto-product-tests/bin/run.sh -t sql_tests.testcases.system.selectInformationSchemaTables
    ```

    where `<debug port>` is the port over which the test JVM and the
    debugger will communicate. By default IntelliJ uses `5005`. Also
    note that execution of the product test will be suspended until a
    debugger is attached.

3. Set a breakpoint at the beginning of the `com.teradata.tempto.internal.convention.ConventionBasedTestFactory#createTestCases`
method. This is the main entry point for the convention based tests. When
opening the `ConventionBasedTestFactory` class for the first time, IntelliJ
will display a de-compiled version because `ConventionBasedTestFactory` is
part of Tempto and not Presto. To download the actual sources make sure
to the press the 'Download sources' button that should appear in the upper
right hand corner of the editor window.

4. [Create a remote run configuration in IntelliJ](https://www.jetbrains.com/help/idea/2016.1/run-debug-configuration-remote.html?origin=old_help).
If the debug port in the step above was `5005`, then no changes to the
remote run configuration are required. This configuration will act as
the debugger.

5. Run the remote configuration. If the debugger successfully attaches,
execution of the product test will resume until the breakpoint is hit. At
this stage the following components should be running: a container with
Hadoop, an IntelliJ run configuration JVM running Presto, a JVM
running the product tests and an IntelliJ remote run configuration JVM
running the debugger.

## Troubleshooting

Use the `docker-compose` (probably using a [wrapper](#use-the-docker-compose-wrappers))
and `docker` utilities to control and troubleshoot containers.
In the following examples ``<profile>`` is [profile](#profile).

1. Use the following command to view output from running containers:

    ```
    presto-product-tests/conf/docker/<profile>/compose.sh logs
    ```

2. To connect to a running container in an interactive Bash shell to
examine state and debug as necessary, use the following commands:

    ```
    # Find the ID of the desired container
    docker ps
    # Connect to running container
    docker exec -ti <container-id> /bin/bash
    ```

3. To reset the Hadoop container when debugging tests, first teardown the
container and then pull from Docker Hub to ensure the latest version has
been downloaded:

    ```
    # Stop Hadoop container (the down command stops and removes containers,
    # network, images, and volumes). This effectively resets the container.
    presto-product-tests/conf/docker/<profile>/compose.sh down
    # Pull from Docker Hub to ensure the latest version of the image is
    # downloaded.
    presto-product-tests/conf/docker/<profile>/compose.sh pull
    ```


text:
require_relative "../kamayan"

# This serving will build on what you made in the last serving. A doubly linked
# list is the same as a linked list, except each node points to both the
# previous and the next node in the list. This collection is ideal for when you
# only want to interact with the first or last item of a collection.
#
# Feel free to copy any code you wrote for the LinkedList into the
# DoublyLinkedList, though you might need to add to the behavior. You will find
# the stub class in doubly_linked_list.rb along with further instructions.
#
# Diagram of a doubly linked list:
#
#            @size = 3
#
#            @head                         @tail
#              |                             |
#              v                             v
#            +---+ -- child --> +---+ ---> +---+ ---> nil
#            | a |              | b |      | c |
#   nil <--- +---+ <-- prev --- +---+ <--- +---+
#
class Serving04DoublyLinkedLists < Attestify::Test
  def test_reverse_shovel_exists
    assert_method_exists DoublyLinkedList, :>>, 1
  end

  def test_reverse_shovel_adds_to_the_beginning
    linked_list = DoublyLinkedList.new
    linked_list >> 42
    assert_equal 42, linked_list.instance_variable_get(:@head).value
    linked_list >> 43
    assert_equal 43, linked_list.instance_variable_get(:@head).value
    assert_equal 42, linked_list.instance_variable_get(:@head).child.value
    assert_nil linked_list.instance_variable_get(:@head).child.child
  end

  def test_reverse_shovel_updates_previous_links
    linked_list = DoublyLinkedList.new
    assert_nil linked_list.instance_variable_get(:@tail)
    linked_list >> 42
    assert_equal 42, linked_list.instance_variable_get(:@tail).value
    linked_list >> 43
    assert_equal 42, linked_list.instance_variable_get(:@tail).value
    assert_equal 43, linked_list.instance_variable_get(:@tail).previous.value
    assert_nil linked_list.instance_variable_get(:@tail).previous.previous
  end

  def test_reverse_shovel_increases_the_size
    linked_list = DoublyLinkedList.new
    linked_list >> 42
    assert_equal 1, linked_list.size
    linked_list >> 43
    assert_equal 2, linked_list.size
  end

  def test_reverse_shovel_returns_self_so_that_it_is_chainable
    linked_list = DoublyLinkedList.new
    linked_list >> 42 >> 43
    assert_equal 43, linked_list.instance_variable_get(:@head).value
    assert_equal 42, linked_list.instance_variable_get(:@head).child.value
    assert_nil linked_list.instance_variable_get(:@head).child.child
  end

  def test_reverse_shovel_can_be_called_a_lot
    linked_list = DoublyLinkedList.new
    100.times { linked_list >> 42 }
    assert_equal 100, linked_list.size

    node = linked_list.instance_variable_get(:@head)
    100.times do
      assert_equal 42, node.value
      node = node.child
    end
  end

  def test_shovel_exists
    assert_method_exists DoublyLinkedList, :<<, 1
  end

  def test_shovel_adds_to_the_end
    linked_list = DoublyLinkedList.new
    linked_list << 42
    assert_equal 42, linked_list.instance_variable_get(:@head).value
    linked_list << 43
    assert_equal 42, linked_list.instance_variable_get(:@head).value
    assert_equal 43, linked_list.instance_variable_get(:@head).child.value
    assert_nil linked_list.instance_variable_get(:@head).child.child
  end

  def test_shovel_updates_previous_links
    linked_list = DoublyLinkedList.new
    assert_nil linked_list.instance_variable_get(:@tail)
    linked_list << 42
    assert_equal 42, linked_list.instance_variable_get(:@tail).value
    linked_list << 43
    assert_equal 43, linked_list.instance_variable_get(:@tail).value
    assert_equal 42, linked_list.instance_variable_get(:@tail).previous.value
    assert_nil linked_list.instance_variable_get(:@tail).previous.previous
  end

  def test_shovel_increases_the_size
    linked_list = DoublyLinkedList.new
    linked_list << 42
    assert_equal 1, linked_list.size
    linked_list << 43
    assert_equal 2, linked_list.size
  end

  def test_shovel_returns_self_so_that_it_is_chainable
    linked_list = DoublyLinkedList.new
    linked_list << 42 << 43
    assert_equal 42, linked_list.instance_variable_get(:@head).value
    assert_equal 43, linked_list.instance_variable_get(:@head).child.value
    assert_nil linked_list.instance_variable_get(:@head).child.child
  end

  def test_shovel_can_be_called_a_lot
    linked_list = DoublyLinkedList.new
    100.times { linked_list << 42 }
    assert_equal 100, linked_list.size

    node = linked_list.instance_variable_get(:@head)
    100.times do
      assert_equal 42, node.value
      node = node.child
    end
  end

  def test_shovel_and_reverse_shovel_are_chainable_together
    linked_list = DoublyLinkedList.new
    linked_list << 42 << 43 >> 2 >> 1
    assert_equal 1, linked_list.instance_variable_get(:@head).value
    assert_equal 2, linked_list.instance_variable_get(:@head).child.value
    assert_equal 42, linked_list.instance_variable_get(:@head).child.child.value
    assert_equal 43, linked_list.instance_variable_get(:@head).child.child.child.value
    assert_nil linked_list.instance_variable_get(:@head).child.child.child.child
  end

  def test_chained_shovel_and_reverse_shovel_increases_the_size
    linked_list = DoublyLinkedList.new
    linked_list << 42 << 43 >> 2 >> 1
    assert_equal 4, linked_list.size
  end

  def test_first_exists
    assert_method_exists DoublyLinkedList, :first, 0
  end

  def test_first_cannot_be_called_on_empty_list
    linked_list = DoublyLinkedList.new
    assert_raises(IndexError) { linked_list.first }
  end

  def test_first_returns_the_first_element
    linked_list = DoublyLinkedList.new << 1
    assert_equal 1, linked_list.first
    linked_list >> 2
    assert_equal 2, linked_list.first
    linked_list >> 42
    assert_equal 42, linked_list.first
    linked_list >> 43
    assert_equal 43, linked_list.first
  end

  def test_last_exists
    assert_method_exists DoublyLinkedList, :last, 0
  end

  def test_last_cannot_be_called_on_empty_list
    linked_list = DoublyLinkedList.new
    assert_raises(IndexError) { linked_list.last }
  end

  def test_last_returns_the_last_element
    linked_list = DoublyLinkedList.new << 1
    assert_equal 1, linked_list.last
    linked_list << 2
    assert_equal 2, linked_list.last
    linked_list << 42
    assert_equal 42, linked_list.last
    linked_list << 43
    assert_equal 43, linked_list.last
  end

  def test_delete_first_exists
    assert_method_exists DoublyLinkedList, :delete_first, 0
  end

  def test_delete_first_cannot_delete_from_an_empty_list
    linked_list = DoublyLinkedList.new
    assert_raises(IndexError) { linked_list.delete_first }
  end

  def test_delete_first_removes_the_first_element
    linked_list = DoublyLinkedList.new << 1 << 2 << 3
    linked_list.delete_first
    assert_equal 2, linked_list.first
    linked_list.delete_first
    assert_equal 3, linked_list.first
  end

  def test_delete_first_returns_the_deleted_element
    linked_list = DoublyLinkedList.new << 1 << 2 << 3
    assert_equal 1, linked_list.delete_first
    assert_equal 2, linked_list.delete_first
    assert_equal 3, linked_list.delete_first
  end

  def test_delete_first_updates_the_size
    linked_list = DoublyLinkedList.new << 1 << 2 << 3
    linked_list.delete_first
    assert_equal 2, linked_list.size
    linked_list.delete_first
    assert_equal 1, linked_list.size
    linked_list.delete_first
    assert_equal 0, linked_list.size
  end

  def test_delete_first_can_be_called_a_lot
    linked_list = DoublyLinkedList.new
    100.times { linked_list << 42 }
    100.times { linked_list.delete_first }
    assert_equal 0, linked_list.size
  end

  def test_delete_first_updates_child_links
    linked_list = DoublyLinkedList.new << 1 << 2 << 3
    linked_list.delete_first
    assert_equal 2, linked_list.instance_variable_get(:@head).value
    assert_equal 3, linked_list.instance_variable_get(:@head).child.value
    assert_nil linked_list.instance_variable_get(:@head).child.child

    linked_list.delete_first
    assert_equal 3, linked_list.instance_variable_get(:@head).value
    assert_nil linked_list.instance_variable_get(:@head).child

    linked_list.delete_first
    assert_nil linked_list.instance_variable_get(:@head)
  end

  def test_delete_first_updates_previous_links
    linked_list = DoublyLinkedList.new << 1 << 2 << 3
    linked_list.delete_first
    assert_equal 3, linked_list.instance_variable_get(:@tail).value
    assert_equal 2, linked_list.instance_variable_get(:@tail).previous.value
    assert_nil linked_list.instance_variable_get(:@tail).previous.previous

    linked_list.delete_first
    assert_equal 3, linked_list.instance_variable_get(:@tail).value
    assert_nil linked_list.instance_variable_get(:@tail).previous

    linked_list.delete_first
    assert_nil linked_list.instance_variable_get(:@tail)
  end

  def test_delete_last_exists
    assert_method_exists DoublyLinkedList, :delete_last, 0
  end

  def test_delete_last_cannot_delete_from_an_empty_list
    linked_list = DoublyLinkedList.new
    assert_raises(IndexError) { linked_list.delete_last }
  end

  def test_delete_last_removes_the_last_element
    linked_list = DoublyLinkedList.new << 1 << 2 << 3
    linked_list.delete_last
    assert_equal 2, linked_list.last
    linked_list.delete_last
    assert_equal 1, linked_list.last
  end

  def test_delete_last_returns_the_deleted_element
    linked_list = DoublyLinkedList.new << 1 << 2 << 3
    assert_equal 3, linked_list.delete_last
    assert_equal 2, linked_list.delete_last
    assert_equal 1, linked_list.delete_last
  end

  def test_delete_last_updates_the_size
    linked_list = DoublyLinkedList.new << 1 << 2 << 3
    linked_list.delete_last
    assert_equal 2, linked_list.size
    linked_list.delete_last
    assert_equal 1, linked_list.size
    linked_list.delete_last
    assert_equal 0, linked_list.size
  end

  def test_delete_last_can_be_called_a_lot
    linked_list = DoublyLinkedList.new
    100.times { linked_list << 42 }
    100.times { linked_list.delete_last }
    assert_equal 0, linked_list.size
  end

  def test_delete_last_updates_child_links
    linked_list = DoublyLinkedList.new << 1 << 2 << 3
    linked_list.delete_last
    assert_equal 1, linked_list.instance_variable_get(:@head).value
    assert_equal 2, linked_list.instance_variable_get(:@head).child.value
    assert_nil linked_list.instance_variable_get(:@head).child.child

    linked_list.delete_last
    assert_equal 1, linked_list.instance_variable_get(:@head).value
    assert_nil linked_list.instance_variable_get(:@head).child

    linked_list.delete_last
    assert_nil linked_list.instance_variable_get(:@head)
  end

  def test_delete_last_updates_previous_links
    linked_list = DoublyLinkedList.new << 1 << 2 << 3
    linked_list.delete_last
    assert_equal 2, linked_list.instance_variable_get(:@tail).value
    assert_equal 1, linked_list.instance_variable_get(:@tail).previous.value
    assert_nil linked_list.instance_variable_get(:@tail).previous.previous

    linked_list.delete_last
    assert_equal 1, linked_list.instance_variable_get(:@tail).value
    assert_nil linked_list.instance_variable_get(:@tail).previous

    linked_list.delete_last
    assert_nil linked_list.instance_variable_get(:@tail)
  end

  def test_each_exists
    assert_method_exists DoublyLinkedList, :each, 0
  end

  def test_each_yields_to_nothing_when_the_list_is_empty
    DoublyLinkedList.new.each do |element|
      flunk "Expected no yield!"
    end
  end

  def test_each_yields_to_the_elements_in_order
    linked_list = DoublyLinkedList.new << 1 << 2 << 42 << 43
    actual_elements = []
    linked_list.each { |element| actual_elements << element }
    assert_equal [1, 2, 42, 43], actual_elements
  end

  def test_each_returns_self_so_it_can_be_chained
    linked_list = DoublyLinkedList.new
    assert_equal(linked_list, linked_list.each { |_| })

    linked_list << 1 << 2 << 42 << 43
    assert_equal(linked_list, linked_list.each { |_| })
  end

  def test_each_reversed_exists
    assert_method_exists DoublyLinkedList, :each_reversed, 0
  end

  def test_each_reversed_yields_to_nothing_when_the_list_is_empty
    DoublyLinkedList.new.each_reversed do |element|
      flunk "Expected no yield!"
    end
  end

  def test_each_reversed_yields_to_the_elements_in_reverse_order
    linked_list = DoublyLinkedList.new << 1 << 2 << 42 << 43
    actual_elements = []
    linked_list.each_reversed { |element| actual_elements << element }
    assert_equal [43, 42, 2, 1], actual_elements
  end

  def test_each_reversed_returns_self_so_it_can_be_chained
    linked_list = DoublyLinkedList.new
    assert_equal(linked_list, linked_list.each_reversed { |_| })

    linked_list << 1 << 2 << 42 << 43
    assert_equal(linked_list, linked_list.each_reversed { |_| })
  end
end