text:
#include <linux/module.h>
#include <linux/delay.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>

#include <sound/uda134x.h>
#include <sound/l3.h>

#include "uda134x.h"

#define POWER_OFF_ON_STANDBY 1
/*
  ALSA SOC usually puts the device in standby mode when it's not used
  for sometime. If you define POWER_OFF_ON_STANDBY the driver will
  turn off the ADC/DAC when this callback is invoked and turn it back
  on when needed. Unfortunately this will result in a very light bump
  (it can be audible only with good earphones). If this bothers you
  just comment this line, you will have slightly higher power
  consumption . Please note that sending the L3 command for ADC is
  enough to make the bump, so it doesn't make difference if you
  completely take off power from the codec.
 */

#define UDA134X_RATES SNDRV_PCM_RATE_8000_48000
#define UDA134X_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
		SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE)

struct uda134x_priv {
	int sysclk;
	int dai_fmt;

	struct snd_pcm_substream *master_substream;
	struct snd_pcm_substream *slave_substream;
};

/* In-data addresses are hard-coded into the reg-cache values */
static const char uda134x_reg[UDA134X_REGS_NUM] = {
	/* Extended address registers */
	0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
	/* Status, data regs */
	0x00, 0x83, 0x00, 0x40, 0x80, 0x00,
};

/*
 * The codec has no support for reading its registers except for peak level...
 */
static inline unsigned int uda134x_read_reg_cache(struct snd_soc_codec *codec,
	unsigned int reg)
{
	u8 *cache = codec->reg_cache;

	if (reg >= UDA134X_REGS_NUM)
		return -1;
	return cache[reg];
}

/*
 * Write the register cache
 */
static inline void uda134x_write_reg_cache(struct snd_soc_codec *codec,
	u8 reg, unsigned int value)
{
	u8 *cache = codec->reg_cache;

	if (reg >= UDA134X_REGS_NUM)
		return;
	cache[reg] = value;
}

/*
 * Write to the uda134x registers
 *
 */
static int uda134x_write(struct snd_soc_codec *codec, unsigned int reg,
	unsigned int value)
{
	int ret;
	u8 addr;
	u8 data = value;
	struct uda134x_platform_data *pd = codec->control_data;

	pr_debug("%s reg: %02X, value:%02X\n", __func__, reg, value);

	if (reg >= UDA134X_REGS_NUM) {
		printk(KERN_ERR "%s unkown register: reg: %u",
		       __func__, reg);
		return -EINVAL;
	}

	uda134x_write_reg_cache(codec, reg, value);

	switch (reg) {
	case UDA134X_STATUS0:
	case UDA134X_STATUS1:
		addr = UDA134X_STATUS_ADDR;
		break;
	case UDA134X_DATA000:
	case UDA134X_DATA001:
	case UDA134X_DATA010:
		addr = UDA134X_DATA0_ADDR;
		break;
	case UDA134X_DATA1:
		addr = UDA134X_DATA1_ADDR;
		break;
	default:
		/* It's an extended address register */
		addr =  (reg | UDA134X_EXTADDR_PREFIX);

		ret = l3_write(&pd->l3,
			       UDA134X_DATA0_ADDR, &addr, 1);
		if (ret != 1)
			return -EIO;

		addr = UDA134X_DATA0_ADDR;
		data = (value | UDA134X_EXTDATA_PREFIX);
		break;
	}

	ret = l3_write(&pd->l3,
		       addr, &data, 1);
	if (ret != 1)
		return -EIO;

	return 0;
}

static inline void uda134x_reset(struct snd_soc_codec *codec)
{
	u8 reset_reg = uda134x_read_reg_cache(codec, UDA134X_STATUS0);
	uda134x_write(codec, UDA134X_STATUS0, reset_reg | (1<<6));
	msleep(1);
	uda134x_write(codec, UDA134X_STATUS0, reset_reg & ~(1<<6));
}

static int uda134x_mute(struct snd_soc_dai *dai, int mute)
{
	struct snd_soc_codec *codec = dai->codec;
	u8 mute_reg = uda134x_read_reg_cache(codec, UDA134X_DATA010);

	pr_debug("%s mute: %d\n", __func__, mute);

	if (mute)
		mute_reg |= (1<<2);
	else
		mute_reg &= ~(1<<2);

	uda134x_write(codec, UDA134X_DATA010, mute_reg);

	return 0;
}

static int uda134x_startup(struct snd_pcm_substream *substream,
	struct snd_soc_dai *dai)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_device *socdev = rtd->socdev;
	struct snd_soc_codec *codec = socdev->card->codec;
	struct uda134x_priv *uda134x = codec->private_data;
	struct snd_pcm_runtime *master_runtime;

	if (uda134x->master_substream) {
		master_runtime = uda134x->master_substream->runtime;

		pr_debug("%s constraining to %d bits at %d\n", __func__,
			 master_runtime->sample_bits,
			 master_runtime->rate);

		snd_pcm_hw_constraint_minmax(substream->runtime,
					     SNDRV_PCM_HW_PARAM_RATE,
					     master_runtime->rate,
					     master_runtime->rate);

		snd_pcm_hw_constraint_minmax(substream->runtime,
					     SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
					     master_runtime->sample_bits,
					     master_runtime->sample_bits);

		uda134x->slave_substream = substream;
	} else
		uda134x->master_substream = substream;

	return 0;
}

static void uda134x_shutdown(struct snd_pcm_substream *substream,
	struct snd_soc_dai *dai)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_device *socdev = rtd->socdev;
	struct snd_soc_codec *codec = socdev->card->codec;
	struct uda134x_priv *uda134x = codec->private_data;

	if (uda134x->master_substream == substream)
		uda134x->master_substream = uda134x->slave_substream;

	uda134x->slave_substream = NULL;
}

static int uda134x_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params,
	struct snd_soc_dai *dai)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
	struct snd_soc_device *socdev = rtd->socdev;
	struct snd_soc_codec *codec = socdev->card->codec;
	struct uda134x_priv *uda134x = codec->private_data;
	u8 hw_params;

	if (substream == uda134x->slave_substream) {
		pr_debug("%s ignoring hw_params for slave substream\n",
			 __func__);
		return 0;
	}

	hw_params = uda134x_read_reg_cache(codec, UDA134X_STATUS0);
	hw_params &= STATUS0_SYSCLK_MASK;
	hw_params &= STATUS0_DAIFMT_MASK;

	pr_debug("%s sysclk: %d, rate:%d\n", __func__,
		 uda134x->sysclk, params_rate(params));

	/* set SYSCLK / fs ratio */
	switch (uda134x->sysclk / params_rate(params)) {
	case 512:
		break;
	case 384:
		hw_params |= (1<<4);
		break;
	case 256:
		hw_params |= (1<<5);
		break;
	default:
		printk(KERN_ERR "%s unsupported fs\n", __func__);
		return -EINVAL;
	}

	pr_debug("%s dai_fmt: %d, params_format:%d\n", __func__,
		 uda134x->dai_fmt, params_format(params));

	/* set DAI format and word length */
	switch (uda134x->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_I2S:
		break;
	case SND_SOC_DAIFMT_RIGHT_J:
		switch (params_format(params)) {
		case SNDRV_PCM_FORMAT_S16_LE:
			hw_params |= (1<<1);
			break;
		case SNDRV_PCM_FORMAT_S18_3LE:
			hw_params |= (1<<2);
			break;
		case SNDRV_PCM_FORMAT_S20_3LE:
			hw_params |= ((1<<2) | (1<<1));
			break;
		default:
			printk(KERN_ERR "%s unsupported format (right)\n",
			       __func__);
			return -EINVAL;
		}
		break;
	case SND_SOC_DAIFMT_LEFT_J:
		hw_params |= (1<<3);
		break;
	default:
		printk(KERN_ERR "%s unsupported format\n", __func__);
		return -EINVAL;
	}

	uda134x_write(codec, UDA134X_STATUS0, hw_params);

	return 0;
}

static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
				  int clk_id, unsigned int freq, int dir)
{
	struct snd_soc_codec *codec = codec_dai->codec;
	struct uda134x_priv *uda134x = codec->private_data;

	pr_debug("%s clk_id: %d, freq: %u, dir: %d\n", __func__,
		 clk_id, freq, dir);

	/* Anything between 256fs*8Khz and 512fs*48Khz should be acceptable
	   because the codec is slave. Of course limitations of the clock
	   master (the IIS controller) apply.
	   We'll error out on set_hw_params if it's not OK */
	if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
		uda134x->sysclk = freq;
		return 0;
	}

	printk(KERN_ERR "%s unsupported sysclk\n", __func__);
	return -EINVAL;
}

static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai,
			       unsigned int fmt)
{
	struct snd_soc_codec *codec = codec_dai->codec;
	struct uda134x_priv *uda134x = codec->private_data;

	pr_debug("%s fmt: %08X\n", __func__, fmt);

	/* codec supports only full slave mode */
	if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
		printk(KERN_ERR "%s unsupported slave mode\n", __func__);
		return -EINVAL;
	}

	/* no support for clock inversion */
	if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {
		printk(KERN_ERR "%s unsupported clock inversion\n", __func__);
		return -EINVAL;
	}

	/* We can't setup DAI format here as it depends on the word bit num */
	/* so let's just store the value for later */
	uda134x->dai_fmt = fmt;

	return 0;
}

static int uda134x_set_bias_level(struct snd_soc_codec *codec,
				  enum snd_soc_bias_level level)
{
	u8 reg;
	struct uda134x_platform_data *pd = codec->control_data;
	int i;
	u8 *cache = codec->reg_cache;

	pr_debug("%s bias level %d\n", __func__, level);

	switch (level) {
	case SND_SOC_BIAS_ON:
		/* ADC, DAC on */
		reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
		uda134x_write(codec, UDA134X_STATUS1, reg | 0x03);
		break;
	case SND_SOC_BIAS_PREPARE:
		/* power on */
		if (pd->power) {
			pd->power(1);
			/* Sync reg_cache with the hardware */
			for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++)
				codec->write(codec, i, *cache++);
		}
		break;
	case SND_SOC_BIAS_STANDBY:
		/* ADC, DAC power off */
		reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
		uda134x_write(codec, UDA134X_STATUS1, reg & ~(0x03));
		break;
	case SND_SOC_BIAS_OFF:
		/* power off */
		if (pd->power)
			pd->power(0);
		break;
	}
	codec->bias_level = level;
	return 0;
}

static const char *uda134x_dsp_setting[] = {"Flat", "Minimum1",
					    "Minimum2", "Maximum"};
static const char *uda134x_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
static const char *uda134x_mixmode[] = {"Differential", "Analog1",
					"Analog2", "Both"};

static const struct soc_enum uda134x_mixer_enum[] = {
SOC_ENUM_SINGLE(UDA134X_DATA010, 0, 0x04, uda134x_dsp_setting),
SOC_ENUM_SINGLE(UDA134X_DATA010, 3, 0x04, uda134x_deemph),
SOC_ENUM_SINGLE(UDA134X_EA010, 0, 0x04, uda134x_mixmode),
};

static const struct snd_kcontrol_new uda1341_snd_controls[] = {
SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
SOC_SINGLE("Capture Volume", UDA134X_EA010, 2, 0x07, 0),
SOC_SINGLE("Analog1 Volume", UDA134X_EA000, 0, 0x1F, 1),
SOC_SINGLE("Analog2 Volume", UDA134X_EA001, 0, 0x1F, 1),

SOC_SINGLE("Mic Sensitivity", UDA134X_EA010, 2, 7, 0),
SOC_SINGLE("Mic Volume", UDA134X_EA101, 0, 0x1F, 0),

SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0),
SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0),

SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]),
SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
SOC_ENUM("Input Mux", uda134x_mixer_enum[2]),

SOC_SINGLE("AGC Switch", UDA134X_EA100, 4, 1, 0),
SOC_SINGLE("AGC Target Volume", UDA134X_EA110, 0, 0x03, 1),
SOC_SINGLE("AGC Timing", UDA134X_EA110, 2, 0x07, 0),

SOC_SINGLE("DAC +6dB Switch", UDA134X_STATUS1, 6, 1, 0),
SOC_SINGLE("ADC +6dB Switch", UDA134X_STATUS1, 5, 1, 0),
SOC_SINGLE("ADC Polarity Switch", UDA134X_STATUS1, 4, 1, 0),
SOC_SINGLE("DAC Polarity Switch", UDA134X_STATUS1, 3, 1, 0),
SOC_SINGLE("Double Speed Playback Switch", UDA134X_STATUS1, 2, 1, 0),
SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
};

static const struct snd_kcontrol_new uda1340_snd_controls[] = {
SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),

SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0),
SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0),

SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]),
SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),

SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
};

static struct snd_soc_dai_ops uda134x_dai_ops = {
	.startup	= uda134x_startup,
	.shutdown	= uda134x_shutdown,
	.hw_params	= uda134x_hw_params,
	.digital_mute	= uda134x_mute,
	.set_sysclk	= uda134x_set_dai_sysclk,
	.set_fmt	= uda134x_set_dai_fmt,
};

struct snd_soc_dai uda134x_dai = {
	.name = "UDA134X",
	/* playback capabilities */
	.playback = {
		.stream_name = "Playback",
		.channels_min = 1,
		.channels_max = 2,
		.rates = UDA134X_RATES,
		.formats = UDA134X_FORMATS,
	},
	/* capture capabilities */
	.capture = {
		.stream_name = "Capture",
		.channels_min = 1,
		.channels_max = 2,
		.rates = UDA134X_RATES,
		.formats = UDA134X_FORMATS,
	},
	/* pcm operations */
	.ops = &uda134x_dai_ops,
};
EXPORT_SYMBOL(uda134x_dai);

static int uda134x_soc_probe(struct platform_device *pdev)
{
	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
	struct snd_soc_codec *codec;
	struct uda134x_priv *uda134x;
	void *codec_setup_data = socdev->codec_data;
	int ret = -ENOMEM;
	struct uda134x_platform_data *pd;

	printk(KERN_INFO "UDA134X SoC Audio Codec\n");

	if (!codec_setup_data) {
		printk(KERN_ERR "UDA134X SoC codec: "
		       "missing L3 bitbang function\n");
		return -ENODEV;
	}

	pd = codec_setup_data;
	switch (pd->model) {
	case UDA134X_UDA1340:
	case UDA134X_UDA1341:
	case UDA134X_UDA1344:
		break;
	default:
		printk(KERN_ERR "UDA134X SoC codec: "
		       "unsupported model %d\n",
			pd->model);
		return -EINVAL;
	}

	socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
	if (socdev->card->codec == NULL)
		return ret;

	codec = socdev->card->codec;

	uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL);
	if (uda134x == NULL)
		goto priv_err;
	codec->private_data = uda134x;

	codec->reg_cache = kmemdup(uda134x_reg, sizeof(uda134x_reg),
				   GFP_KERNEL);
	if (codec->reg_cache == NULL)
		goto reg_err;

	mutex_init(&codec->mutex);

	codec->reg_cache_size = sizeof(uda134x_reg);
	codec->reg_cache_step = 1;

	codec->name = "UDA134X";
	codec->owner = THIS_MODULE;
	codec->dai = &uda134x_dai;
	codec->num_dai = 1;
	codec->read = uda134x_read_reg_cache;
	codec->write = uda134x_write;
#ifdef POWER_OFF_ON_STANDBY
	codec->set_bias_level = uda134x_set_bias_level;
#endif
	INIT_LIST_HEAD(&codec->dapm_widgets);
	INIT_LIST_HEAD(&codec->dapm_paths);

	codec->control_data = codec_setup_data;

	if (pd->power)
		pd->power(1);

	uda134x_reset(codec);

	/* register pcms */
	ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
	if (ret < 0) {
		printk(KERN_ERR "UDA134X: failed to register pcms\n");
		goto pcm_err;
	}

	switch (pd->model) {
	case UDA134X_UDA1340:
	case UDA134X_UDA1344:
		ret = snd_soc_add_controls(codec, uda1340_snd_controls,
					ARRAY_SIZE(uda1340_snd_controls));
	break;
	case UDA134X_UDA1341:
		ret = snd_soc_add_controls(codec, uda1341_snd_controls,
					ARRAY_SIZE(uda1341_snd_controls));
	break;
	default:
		printk(KERN_ERR "%s unkown codec type: %d",
			__func__, pd->model);
	return -EINVAL;
	}

	if (ret < 0) {
		printk(KERN_ERR "UDA134X: failed to register controls\n");
		goto pcm_err;
	}

	ret = snd_soc_init_card(socdev);
	if (ret < 0) {
		printk(KERN_ERR "UDA134X: failed to register card\n");
		goto card_err;
	}

	return 0;

card_err:
	snd_soc_free_pcms(socdev);
	snd_soc_dapm_free(socdev);
pcm_err:
	kfree(codec->reg_cache);
reg_err:
	kfree(codec->private_data);
priv_err:
	kfree(codec);
	return ret;
}

/* power down chip */
static int uda134x_soc_remove(struct platform_device *pdev)
{
	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
	struct snd_soc_codec *codec = socdev->card->codec;

	uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
	uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);

	snd_soc_free_pcms(socdev);
	snd_soc_dapm_free(socdev);

	kfree(codec->private_data);
	kfree(codec->reg_cache);
	kfree(codec);

	return 0;
}

#if defined(CONFIG_PM)
static int uda134x_soc_suspend(struct platform_device *pdev,
						pm_message_t state)
{
	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
	struct snd_soc_codec *codec = socdev->card->codec;

	uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
	uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
	return 0;
}

static int uda134x_soc_resume(struct platform_device *pdev)
{
	struct snd_soc_device *socdev = platform_get_drvdata(pdev);
	struct snd_soc_codec *codec = socdev->card->codec;

	uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
	uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
	return 0;
}
#else
#define uda134x_soc_suspend NULL
#define uda134x_soc_resume NULL
#endif /* CONFIG_PM */

struct snd_soc_codec_device soc_codec_dev_uda134x = {
	.probe =        uda134x_soc_probe,
	.remove =       uda134x_soc_remove,
	.suspend =      uda134x_soc_suspend,
	.resume =       uda134x_soc_resume,
};
EXPORT_SYMBOL_GPL(soc_codec_dev_uda134x);

static int __init uda134x_init(void)
{
	return snd_soc_register_dai(&uda134x_dai);
}
module_init(uda134x_init);

static void __exit uda134x_exit(void)
{
	snd_soc_unregister_dai(&uda134x_dai);
}
module_exit(uda134x_exit);

MODULE_DESCRIPTION("UDA134X ALSA soc codec driver");
MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
MODULE_LICENSE("GPL");


text:
package net.roboconf.plugin.puppet.internal;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;

import net.roboconf.core.internal.tests.TestUtils;
import net.roboconf.core.model.beans.Component;
import net.roboconf.core.model.beans.Import;
import net.roboconf.core.model.beans.Instance;
import net.roboconf.core.model.beans.Instance.InstanceStatus;
import net.roboconf.core.model.helpers.InstanceHelpers;
import net.roboconf.core.utils.ProgramUtils;
import net.roboconf.core.utils.Utils;
import net.roboconf.plugin.api.PluginException;

/**
 * @author Vincent Zurczak - Linagora
 */
public class PluginPuppetTest {

	private final static File OUTPUT_DIR = new File( "/tmp/roboconf-test-for-puppet" );

	private final Instance inst = new Instance( "sample" )
			.component( new Component( "some-component" )
			.installerName( PluginPuppet.PLUGIN_NAME ));

	private final File instanceDirectory = InstanceHelpers.findInstanceDirectoryOnAgent( this.inst );
	private PluginPuppet plugin;

	private boolean running = true;

	/**
	 * A method to check that Puppet is installed on the machine.
	 * <p>
	 * If it is not running, tests in this class will be skipped.
	 * </p>
	 */
	@Before
	public void checkPuppetIsInstalled() throws Exception {

		Assume.assumeTrue( this.running );
		try {
			List<String> command = new ArrayList<> ();
			command.add( "puppet" );
			command.add( "--version" );

			Logger logger = Logger.getLogger( getClass().getName());
			ProgramUtils.executeCommand( logger, command, null, null, null, null);

		} catch( Exception e ) {
			Logger logger = Logger.getLogger( getClass().getName());
			logger.warning( "Tests are skipped because Puppet is not installed." );
			Utils.logException( logger, e );

			this.running = false;
			Assume.assumeNoException( e );
		}
	}

	@Before
	public void resetPlugin() throws Exception {
		this.plugin = new PluginPuppet();
		this.plugin.setNames( "app", "test" );
		Utils.createDirectory( OUTPUT_DIR );
	}

	@After
	public void clearPreviousOutputs() throws Exception {
		Utils.deleteFilesRecursively( this.instanceDirectory );
		Utils.deleteFilesRecursively( OUTPUT_DIR );
	}

	@Test
	public void testSetNames() {

		Assert.assertNotNull( this.plugin.agentId );
		this.plugin.agentId = null;
		Assert.assertNull( this.plugin.agentId );

		this.plugin.setNames( "app", null );
		Assert.assertNotNull( this.plugin.agentId );

		this.plugin.setNames( null, "test" );
		Assert.assertNotNull( this.plugin.agentId );
	}

	@Test
	public void testInitialize_withVersion() throws Exception {

		Assume.assumeTrue( this.running );
		copyResources( "/with-version" );

		File[] subFiles = this.instanceDirectory.listFiles();
		Assert.assertNotNull( subFiles );
		Assert.assertEquals( 1, subFiles.length );

		File moduleDirectory = new File( this.instanceDirectory, "sysctl" );
		Assert.assertFalse( moduleDirectory.exists());

		this.plugin.initialize( this.inst );

		subFiles = this.instanceDirectory.listFiles();
		Assert.assertNotNull( subFiles );
		Assert.assertEquals( 2, subFiles.length );

		Assert.assertTrue( moduleDirectory.exists());
		Assert.assertTrue( moduleDirectory.isDirectory());
	}

	@Test
	public void testInitialize_withoutVersion() throws Exception {

		Assume.assumeTrue( this.running );
		copyResources( "/without-version" );

		File[] moduleDirectories = new File[ 2 ];
		moduleDirectories[ 0 ] = new File( this.instanceDirectory, "sysctl" );
		moduleDirectories[ 1 ] = new File( this.instanceDirectory, "redis" );

		for( File f : moduleDirectories )
			Assert.assertFalse( f.getAbsolutePath(), f.exists());

		this.plugin.initialize( this.inst );

		for( File f : moduleDirectories ) {
			Assert.assertTrue( f.getAbsolutePath(), f.exists());
			Assert.assertTrue( f.getAbsolutePath(), f.isDirectory());
		}
	}

	@Test
	public void testInitialize_inexistingDirectory() throws Exception {

		Assume.assumeTrue( this.running );
		Utils.deleteFilesRecursively( this.instanceDirectory );

		this.plugin.initialize( this.inst );
		Assert.assertFalse( this.instanceDirectory.exists());
	}

	@Test( expected = PluginException.class )
	public void testInitialize_withInvalidModule() throws Exception {

		Assume.assumeTrue( this.running );
		copyResources( "/with-invalid-module" );
		this.plugin.initialize( this.inst );
	}

	@Test
	public void testPuppetPlugin_withInit_deploy() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-init" );

		this.plugin.deploy( this.inst );
		checkGeneratedFiles( "WithInit", "stopped" );
	}

	@Test
	public void testPuppetPlugin_withInit_start() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-init" );

		this.plugin.start( this.inst );
		checkGeneratedFiles( "WithInit", "running" );
	}

	@Test
	public void testPuppetPlugin_withInit_stop() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-init" );

		this.plugin.stop( this.inst );
		checkGeneratedFiles( "WithInit", "stopped" );
	}

	@Test
	public void testPuppetPlugin_withInit_undeploy() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-init" );

		this.plugin.undeploy( this.inst );
		checkGeneratedFiles( "WithInit", "" );	// UNDEF
	}

	@Test
	public void testPuppetPlugin_withInit_update() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-init" );

		Map<String,String> variables = new HashMap<> ();
		variables.put( "ip", "127.0.0.1" );

		this.plugin.update(
				this.inst,
				new Import( "/some/path", "component1", variables ),
				InstanceStatus.DEPLOYED_STARTED );

		checkGeneratedFiles( "WithInit", "" );	// UNDEF
	}

	@Test
	public void testPuppetPlugin_withOperations_deploy() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-operations" );

		this.plugin.deploy( this.inst );
		checkGeneratedFiles( "WithOperations", "deploy" );
	}

	@Test
	public void testPuppetPlugin_withOperations_start() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-operations" );

		this.plugin.start( this.inst );
		checkGeneratedFiles( "WithOperations", "start" );
	}

	@Test
	public void testPuppetPlugin_withOperations_stop() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-operations" );

		this.plugin.stop( this.inst );
		checkGeneratedFiles( "WithOperations", "stop" );
	}

	@Test
	public void testPuppetPlugin_withOperations_undeploy() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-operations" );

		this.plugin.undeploy( this.inst );
		checkGeneratedFiles( "WithOperations", "undeploy" );
	}

	@Test
	public void testPuppetPlugin_withOperations_update() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-operations" );

		Map<String,String> variables = new HashMap<> ();
		variables.put( "ip", "127.0.0.1" );

		this.plugin.update(
				this.inst,
				new Import( "/some/path", "component1", variables ),
				InstanceStatus.DEPLOYED_STOPPED );

		checkGeneratedFiles( "WithOperations", "update" );
	}

	@Test( expected = PluginException.class )
	public void testPuppetPlugin_withInit_exception_deploy() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-init-invalid" );
		this.plugin.deploy( this.inst );
	}

	@Test( expected = PluginException.class )
	public void testPuppetPlugin_withInit_exception_start() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-init-invalid" );
		this.plugin.start( this.inst );
	}

	@Test( expected = PluginException.class )
	public void testPuppetPlugin_withInit_exception_stop() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-init-invalid" );
		this.plugin.stop( this.inst );
	}

	@Test( expected = PluginException.class )
	public void testPuppetPlugin_withInit_exception_undeploy() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-init-invalid" );
		this.plugin.undeploy( this.inst );
	}

	@Test( expected = PluginException.class )
	public void testPuppetPlugin_withInit_exception_update() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-init-invalid" );

		Map<String,String> variables = new HashMap<> ();
		variables.put( "ip", "127.0.0.1" );

		this.plugin.update(
				this.inst,
				new Import( "/some/path", "component1", variables ),
				InstanceStatus.DEPLOYED_STARTED );
	}

	@Test( expected = PluginException.class )
	public void testNoModuleDirectory() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		Assert.assertTrue( new File( this.instanceDirectory, "whatever" ).mkdirs());
		Assert.assertTrue( new File( this.instanceDirectory, "whatever.txt" ).createNewFile());
		this.plugin.undeploy( this.inst );
	}

	@Test
	public void testNoScriptToExecute() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		Assert.assertTrue( new File( this.instanceDirectory, "roboconf_empty_puppet_module" ).mkdirs());
		this.plugin.undeploy( this.inst );
		// No error, the execution is skipped
	}

	@Test( expected = PluginException.class )
	public void testPuppetPlugin_withInit_nonZeroCode_deploy() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-init-exit-1" );
		this.plugin.deploy( this.inst );
	}

	@Test( expected = PluginException.class )
	public void testPuppetPlugin_withInit_nonZeroCode_start() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-init-exit-1" );
		this.plugin.start( this.inst );
	}

	@Test( expected = PluginException.class )
	public void testPuppetPlugin_withInit_nonZeroCode_stop() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-init-exit-1" );
		this.plugin.stop( this.inst );
	}

	@Test( expected = PluginException.class )
	public void testPuppetPlugin_withInit_nonZeroCode_undeploy() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-init-exit-1" );
		this.plugin.undeploy( this.inst );
	}

	@Test( expected = PluginException.class )
	public void testPuppetPlugin_withInit_nonZeroCode_update() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-init-exit-1" );

		Map<String,String> variables = new HashMap<> ();
		variables.put( "ip", "127.0.0.1" );

		this.plugin.update(
				this.inst,
				new Import( "/some/path", "component1", variables ),
				InstanceStatus.DEPLOYED_STARTED );
	}

	@Test
	public void testPuppetPlugin_withInit_nonZeroCode_changesAndErrors() throws Exception {

		Assume.assumeTrue( isLinuxSystem());
		copyResources( "/with-init-changes-and-errors" );
		this.plugin.undeploy( this.inst );
	}

	private void checkGeneratedFiles( String prefix, String suffix ) {

		File fromTpl = new File( OUTPUT_DIR, prefix + ".tpl." + suffix );
		Assert.assertTrue( fromTpl.exists());
		Assert.assertTrue( fromTpl.length() > 0 );

		File fromStatic = new File( OUTPUT_DIR, prefix + ".file." + suffix );
		Assert.assertTrue( fromStatic.exists());
		Assert.assertTrue( fromStatic.length() > 0 );

		File[] subFiles = OUTPUT_DIR.listFiles();
		Assert.assertNotNull( subFiles );
		Assert.assertEquals( 2, subFiles.length );
	}

	private void copyResources( String resourcesPath ) throws Exception {
		File toCopy = TestUtils.findTestFile( resourcesPath );
		Utils.copyDirectory( toCopy, this.instanceDirectory);
	}

	private boolean isLinuxSystem() {
		return new File( "/tmp" ).exists();
	}
}

redpajama_set_name: RedPajamaGithub


text:
module KeyValueLogging
  VERSION = "0.0.2"
end


text:
package retrofacebook.processor;

import static com.google.common.truth.Truth.assertAbout;
import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;
import static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.testing.compile.JavaFileObjects;

import junit.framework.TestCase;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.ElementFilter;
import javax.tools.JavaFileObject;

import retrofacebook.processor.RetroFacebookBuilderProcessor;
import retrofacebook.processor.RetroFacebookProcessor;

/**
 * @author emcmanus@google.com (Éamonn McManus)
 */
public class CompilationTest extends TestCase {
  public void testCompilation() {
    // Positive test case that ensures we generate the expected code for at least one case.
    // Most RetroFacebook code-generation tests are functional, meaning that we check that the generated
    // code does the right thing rather than checking what it looks like, but this test is a sanity
    // check that we are not generating correct but weird code.
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  public abstract int buh();",
        "",
        "  public static Baz create(int buh) {",
        "    return new RetroFacebook_Baz(buh);",
        "  }",
        "}");
    JavaFileObject expectedOutput = JavaFileObjects.forSourceLines(
        "foo.bar.RetroFacebook_Baz",
        "package foo.bar;",
        "",
        "final class RetroFacebook_Baz extends Baz {",
        "  private final int buh;",
        "",
        "  RetroFacebook_Baz(int buh) {",
        "    this.buh = buh;",
        "  }",
        "",
        "  @Override public int buh() {",
        "    return buh;",
        "  }",
        "",
        "  @Override public String toString() {",
        "    return \"Baz{\"",
        "        + \"buh=\" + buh",
        "        + \"}\";",
        "  }",
        "",
        "  @Override public boolean equals(Object o) {",
        "    if (o == this) {",
        "      return true;",
        "    }",
        "    if (o instanceof Baz) {",
        "      Baz that = (Baz) o;",
        "      return (this.buh == that.buh());",
        "    }",
        "    return false;",
        "  }",
        "",
        "  @Override public int hashCode() {",
        "    int h = 1;",
        "    h *= 1000003;",
        "    h ^= buh;",
        "    return h;",
        "  }",
        "}"
    );
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor())
        .compilesWithoutError()
        .and().generatesSources(expectedOutput);
  }

  public void testImports() {
    // Test that referring to the same class in two different ways does not confuse the import logic
    // into thinking it is two different classes and that therefore it can't import. The code here
    // is nonsensical but successfully reproduces a real problem, which is that a TypeMirror that is
    // extracted using Elements.getTypeElement(name).asType() does not compare equal to one that is
    // extracted from ExecutableElement.getReturnType(), even though Types.isSameType considers them
    // equal. So unless we are careful, the java.util.Arrays that we import explicitly to use its
    // methods will appear different from the java.util.Arrays that is the return type of the
    // arrays() method here.
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "import java.util.Arrays;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  public abstract int[] ints();",
        "  public abstract Arrays arrays();",
        "",
        "  public static Baz create(int[] ints, Arrays arrays) {",
        "    return new RetroFacebook_Baz(ints, arrays);",
        "  }",
        "}");
    JavaFileObject expectedOutput = JavaFileObjects.forSourceLines(
        "foo.bar.RetroFacebook_Baz",
        "package foo.bar;",
        "",
        "import java.util.Arrays;",
        "",
        "final class RetroFacebook_Baz extends Baz {",
        "  private final int[] ints;",
        "  private final Arrays arrays;",
        "",
        "  RetroFacebook_Baz(int[] ints, Arrays arrays) {",
        "    if (ints == null) {",
        "      throw new NullPointerException(\"Null ints\");",
        "    }",
        "    this.ints = ints;",
        "    if (arrays == null) {",
        "      throw new NullPointerException(\"Null arrays\");",
        "    }",
        "    this.arrays = arrays;",
        "  }",
        "",
        "  @Override public int[] ints() {",
        "    return ints.clone();",
        "  }",
        "",
        "  @Override public Arrays arrays() {",
        "    return arrays;",
        "  }",
        "",
        "  @Override public String toString() {",
        "    return \"Baz{\"",
        "        + \"ints=\" + Arrays.toString(ints) + \", \"",
        "        + \"arrays=\" + arrays",
        "        + \"}\";",
        "  }",
        "",
        "  @Override public boolean equals(Object o) {",
        "    if (o == this) {",
        "      return true;",
        "    }",
        "    if (o instanceof Baz) {",
        "      Baz that = (Baz) o;",
        "      return (Arrays.equals(this.ints, (that instanceof RetroFacebook_Baz) "
                      + "? ((RetroFacebook_Baz) that).ints : that.ints()))",
        "          && (this.arrays.equals(that.arrays()));",
        "    }",
        "    return false;",
        "  }",
        "",
        "  @Override public int hashCode() {",
        "    int h = 1;",
        "    h *= 1000003;",
        "    h ^= Arrays.hashCode(ints);",
        "    h *= 1000003;",
        "    h ^= arrays.hashCode();",
        "    return h;",
        "  }",
        "}"
    );
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor())
        .compilesWithoutError()
        .and().generatesSources(expectedOutput);
  }

  public void testNoMultidimensionalPrimitiveArrays() throws Exception {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  public abstract int[][] ints();",
        "",
        "  public static Baz create(int[][] ints) {",
        "    return new RetroFacebook_Baz(ints);",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor())
        .failsToCompile()
        .withErrorContaining("RetroFacebook class cannot define an array-valued property "
            + "unless it is a primitive array")
        .in(javaFileObject).onLine(7);
  }

  public void testNoObjectArrays() throws Exception {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  public abstract String[] strings();",
        "",
        "  public static Baz create(String[] strings) {",
        "    return new RetroFacebook_Baz(strings);",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor())
        .failsToCompile()
        .withErrorContaining("RetroFacebook class cannot define an array-valued property "
            + "unless it is a primitive array")
        .in(javaFileObject).onLine(7);
  }

  public void testAnnotationOnInterface() throws Exception {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public interface Baz {}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor())
        .failsToCompile()
        .withErrorContaining("RetroFacebook only applies to classes")
        .in(javaFileObject).onLine(6);
  }

  public void testAnnotationOnEnum() throws Exception {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public enum Baz {}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor())
        .failsToCompile()
        .withErrorContaining("RetroFacebook only applies to classes")
        .in(javaFileObject).onLine(6);
  }

  public void testExtendRetroFacebook() throws Exception {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Outer",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "public class Outer {",
        "  @RetroFacebook",
        "  static abstract class Parent {",
        "    static Parent create(int randomProperty) {",
        "      return new RetroFacebook_Outer_Parent(randomProperty);",
        "    }",
        "",
        "    abstract int randomProperty();",
        "  }",
        "",
        "  @RetroFacebook",
        "  static abstract class Child extends Parent {",
        "    static Child create(int randomProperty) {",
        "      return new RetroFacebook_Outer_Child(randomProperty);",
        "    }",
        "",
        "    abstract int randomProperty();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor())
        .failsToCompile()
        .withErrorContaining("may not extend")
        .in(javaFileObject).onLine(16);
  }

  public void testBogusSerialVersionUID() throws Exception {
    String[] mistakes = {
      "final long serialVersionUID = 1234L", // not static
      "static long serialVersionUID = 1234L", // not final
      "static final Long serialVersionUID = 1234L", // not long
      "static final long serialVersionUID = (Long) 1234L", // not a compile-time constant
    };
    for (String mistake : mistakes) {
      JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
          "foo.bar.Baz",
          "package foo.bar;",
          "",
          "import retrofacebook.RetroFacebook;",
          "",
          "@RetroFacebook",
          "public abstract class Baz implements java.io.Serializable {",
          "  " + mistake + ";",
          "",
          "  public abstract int foo();",
          "}");
      assertAbout(javaSource())
          .that(javaFileObject)
          .processedWith(new RetroFacebookProcessor())
          .failsToCompile()
          .withErrorContaining(
              "serialVersionUID must be a static final long compile-time constant")
          .in(javaFileObject).onLine(7);
    }
  }

  public void testNonExistentSuperclass() throws Exception {
    // The main purpose of this test is to check that RetroFacebookProcessor doesn't crash the
    // compiler in this case.
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Existent extends NonExistent {",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor())
        .failsToCompile()
        .withErrorContaining("NonExistent")
        .in(javaFileObject).onLine(6);
  }

  public void testCannotImplementAnnotation() throws Exception {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.RetentionImpl",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "import java.lang.annotation.Retention;",
        "import java.lang.annotation.RetentionPolicy;",
        "",
        "@RetroFacebook",
        "public abstract class RetentionImpl implements Retention {",
        "  public static Retention create(RetentionPolicy policy) {",
        "    return new RetroFacebook_RetentionImpl(policy);",
        "  }",
        "",
        "  @Override public Class<? extends Retention> annotationType() {",
        "    return Retention.class;",
        "  }",
        "",
        "  @Override public boolean equals(Object o) {",
        "    return (o instanceof Retention && value().equals((Retention) o).value());",
        "  }",
        "",
        "  @Override public int hashCode() {",
        "    return (\"value\".hashCode() * 127) ^ value().hashCode();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor())
        .failsToCompile()
        .withErrorContaining("may not be used to implement an annotation interface")
        .in(javaFileObject).onLine(8);
  }

  public void testMissingPropertyType() throws Exception {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  public abstract MissingType missingType();",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor())
        .failsToCompile()
        .withErrorContaining("MissingType")
        .in(javaFileObject).onLine(7);
  }

  public void testMissingGenericPropertyType() throws Exception {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  public abstract MissingType<?> missingType();",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor())
        .failsToCompile()
        .withErrorContaining("MissingType")
        .in(javaFileObject).onLine(7);
  }

  public void testMissingComplexGenericPropertyType() throws Exception {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "import java.util.Map;",
        "import java.util.Set;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  public abstract Map<Set<?>, MissingType<?>> missingType();",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor())
        .failsToCompile()
        .withErrorContaining("MissingType")
        .in(javaFileObject).onLine(10);
  }

  public void testMissingSuperclassGenericParameter() throws Exception {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz<T extends MissingType<?>> {",
        "  public abstract int foo();",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor())
        .failsToCompile()
        .withErrorContaining("MissingType")
        .in(javaFileObject).onLine(6);
  }

  public void testCorrectBuilder() throws Exception {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "import java.util.List;",
        "import javax.annotation.Nullable;",
        "",
        "@RetroFacebook",
        "public abstract class Baz<T extends Number> {",
        "  public abstract int anInt();",
        "  public abstract byte[] aByteArray();",
        "  @Nullable public abstract int[] aNullableIntArray();",
        "  public abstract List<T> aList();",
        "",
        "  public abstract Builder<T> toBuilder();",
        "",
        "  @RetroFacebook.Validate",
        "  void validate() {",
        "    if (anInt() < 0) {",
        "      throw new IllegalStateException(\"Negative integer\");",
        "    }",
        "  }",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder<T extends Number> {",
        "    Builder<T> anInt(int x);",
        "    Builder<T> aByteArray(byte[] x);",
        "    Builder<T> aNullableIntArray(@Nullable int[] x);",
        "    Builder<T> aList(List<T> x);",
        "    Baz<T> build();",
        "  }",
        "",
        "  public static <T extends Number> Builder<T> builder() {",
        "    return RetroFacebook_Baz.builder();",
        "  }",
        "}");
    JavaFileObject expectedOutput = JavaFileObjects.forSourceLines(
        "foo.bar.RetroFacebook_Baz",
        "package foo.bar;",
        "",
        "import java.util.Arrays;",
        "import java.util.BitSet;",
        "import java.util.List;",
        "",
        "final class RetroFacebook_Baz<T extends Number> extends Baz<T> {",
        "  private final int anInt;",
        "  private final byte[] aByteArray;",
        "  private final int[] aNullableIntArray;",
        "  private final List<T> aList;",
        "",
        "  private RetroFacebook_Baz("
            + "int anInt, byte[] aByteArray, int[] aNullableIntArray, List<T> aList) {",
        "    this.anInt = anInt;",
        "    if (aByteArray == null) {",
        "      throw new NullPointerException(\"Null aByteArray\");",
        "    }",
        "    this.aByteArray = aByteArray;",
        "    this.aNullableIntArray = aNullableIntArray;",
        "    if (aList == null) {",
        "      throw new NullPointerException(\"Null aList\");",
        "    }",
        "    this.aList = aList;",
        "  }",
        "",
        "  @Override public int anInt() {",
        "    return anInt;",
        "  }",
        "",
        "  @Override public byte[] aByteArray() {",
        "    return aByteArray.clone();",
        "  }",
        "",
        "  @javax.annotation.Nullable",
        "  @Override public int[] aNullableIntArray() {",
        "    return aNullableIntArray == null ? null : aNullableIntArray.clone();",
        "  }",
        "",
        "  @Override public List<T> aList() {",
        "    return aList;",
        "  }",
        "",
        "  @Override public String toString() {",
        "    return \"Baz{\"",
        "        + \"anInt=\" + anInt + \", \"",
        "        + \"aByteArray=\" + Arrays.toString(aByteArray) + \", \"",
        "        + \"aNullableIntArray=\" + Arrays.toString(aNullableIntArray) + \", \"",
        "        + \"aList=\" + aList",
        "        + \"}\";",
        "  }",
        "",
        "  @Override public boolean equals(Object o) {",
        "    if (o == this) {",
        "      return true;",
        "    }",
        "    if (o instanceof Baz) {",
        "      Baz<?> that = (Baz<?>) o;",
        "      return (this.anInt == that.anInt())",
        "          && (Arrays.equals(this.aByteArray, "
                    + "(that instanceof RetroFacebook_Baz) "
                        + "? ((RetroFacebook_Baz) that).aByteArray : that.aByteArray()))",
        "          && (Arrays.equals(this.aNullableIntArray, "
                    + "(that instanceof RetroFacebook_Baz) "
                        + "? ((RetroFacebook_Baz) that).aNullableIntArray : that.aNullableIntArray()))",
        "          && (this.aList.equals(that.aList()));",
        "    }",
        "    return false;",
        "  }",
        "",
        "  @Override public int hashCode() {",
        "    int h = 1;",
        "    h *= 1000003;",
        "    h ^= anInt;",
        "    h *= 1000003;",
        "    h ^= Arrays.hashCode(aByteArray);",
        "    h *= 1000003;",
        "    h ^= Arrays.hashCode(aNullableIntArray);",
        "    h *= 1000003;",
        "    h ^= aList.hashCode();",
        "    return h;",
        "  }",
        "",
        "  @Override public Baz.Builder<T> toBuilder() {",
        "    return new Builder<T>(this);",
        "  }",
        "",
        "  static final class Builder<T extends Number> implements Baz.Builder<T> {",
        "    private final BitSet set$ = new BitSet();",
        "",
        "    private int anInt;",
        "    private byte[] aByteArray;",
        "    private int[] aNullableIntArray;",
        "    private List<T> aList;",
        "",
        "    Builder() {",
        "    }",
        "",
        "    Builder(Baz<T> source) {",
        "      anInt(source.anInt());",
        "      aByteArray(source.aByteArray());",
        "      aNullableIntArray(source.aNullableIntArray());",
        "      aList(source.aList());",
        "    }",
        "",
        "    @Override",
        "    public Baz.Builder<T> anInt(int anInt) {",
        "      this.anInt = anInt;",
        "      set$.set(0);",
        "      return this;",
        "    }",
        "",
        "    @Override",
        "    public Baz.Builder<T> aByteArray(byte[] aByteArray) {",
        "      this.aByteArray = aByteArray.clone();",
        "      set$.set(1);",
        "      return this;",
        "    }",
        "",
        "    @Override",
        "    public Baz.Builder<T> aNullableIntArray(int[] aNullableIntArray) {",
        "      this.aNullableIntArray = "
                + "(aNullableIntArray == null) ? null : aNullableIntArray.clone();",
        "      return this;",
        "    }",
        "",
        "    @Override",
        "    public Baz.Builder<T> aList(List<T> aList) {",
        "      this.aList = aList;",
        "      set$.set(2);",
        "      return this;",
        "    }",
        "",
        "    @Override",
        "    public Baz<T> build() {",
        "      if (set$.cardinality() < 3) {",
        "        String[] propertyNames = {",
        "          \"anInt\", \"aByteArray\", \"aList\",",
        "        };",
        "        StringBuilder missing = new StringBuilder();",
        "        for (int i = 0; i < 3; i++) {",
        "          if (!set$.get(i)) {",
        "            missing.append(' ').append(propertyNames[i]);",
        "          }",
        "        }",
        "        throw new IllegalStateException(\"Missing required properties:\" + missing);",
        "      }",
        "      Baz<T> result = new RetroFacebook_Baz<T>(",
        "          this.anInt, this.aByteArray, this.aNullableIntArray, this.aList);",
        "      result.validate();",
        "      return result;",
        "    }",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor())
        .compilesWithoutError()
        .and()
        .generatesSources(expectedOutput);
  }

  public void testRetroFacebookBuilderOnTopLevelClass() throws Exception {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Builder",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook.Builder",
        "public interface Builder {",
        "  Builder foo(int x);",
        "  Object build();",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("can only be applied to a class or interface inside")
        .in(javaFileObject).onLine(6);
  }

  public void testRetroFacebookBuilderNotInsideRetroFacebook() throws Exception {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "public abstract class Baz {",
        "  abstract int foo();",
        "",
        "  static Builder builder() {",
        "    return new RetroFacebook_Baz.Builder();",
        "  }",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder {",
        "    Builder foo(int x);",
        "    Baz build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("can only be applied to a class or interface inside")
        .in(javaFileObject).onLine(13);
  }

  public void testRetroFacebookBuilderOnEnum() throws Exception {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  abstract int foo();",
        "",
        "  static Builder builder() {",
        "    return null;",
        "  }",
        "",
        "  @RetroFacebook.Builder",
        "  public enum Builder {}",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("can only apply to a class or an interface")
        .in(javaFileObject).onLine(14);
  }

  public void testRetroFacebookBuilderDuplicate() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  @RetroFacebook.Builder",
        "  public interface Builder1 {",
        "    Baz build();",
        "  }",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder2 {",
        "    Baz build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("already has a Builder: foo.bar.Baz.Builder1")
        .in(javaFileObject).onLine(13);
  }

  public void testRetroFacebookBuilderMissingSetter() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  abstract int blim();",
        "  abstract String blam();",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder {",
        "    Builder blam(String x);",
        "    Baz build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("with this signature: foo.bar.Baz.Builder blim(int)")
        .in(javaFileObject).onLine(11);
  }

  public void testRetroFacebookBuilderMissingSetterUsingSetPrefix() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  abstract int blim();",
        "  abstract String blam();",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder {",
        "    Builder setBlam(String x);",
        "    Baz build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("with this signature: foo.bar.Baz.Builder setBlim(int)")
        .in(javaFileObject).onLine(11);
  }

  public void testRetroFacebookBuilderWrongTypeSetter() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  abstract int blim();",
        "  abstract String blam();",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder {",
        "    Builder blim(String x);",
        "    Builder blam(String x);",
        "    Baz build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("Parameter type should be int")
        .in(javaFileObject).onLine(12);
  }

  public void testRetroFacebookBuilderWrongTypeSetterWithGetPrefix() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  abstract int getBlim();",
        "  abstract String getBlam();",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder {",
        "    Builder blim(String x);",
        "    Builder blam(String x);",
        "    Baz build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("Parameter type should be int")
        .in(javaFileObject).onLine(12);
  }

  public void testRetroFacebookBuilderExtraSetter() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  abstract String blam();",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder {",
        "    Builder blim(int x);",
        "    Builder blam(String x);",
        "    Baz build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("Method does not correspond to a property of foo.bar.Baz")
        .in(javaFileObject).onLine(11);
  }

  public void testRetroFacebookBuilderSetPrefixAndNoSetPrefix() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  abstract int blim();",
        "  abstract String blam();",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder {",
        "    Builder blim(int x);",
        "    Builder setBlam(String x);",
        "    Baz build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("If any setter methods use the setFoo convention then all must")
        .in(javaFileObject).onLine(12);
  }

  public void testRetroFacebookBuilderAlienMethod() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  abstract String blam();",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder {",
        "    Builder blam(String x, String y);",
        "    Baz build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining(
            "Builder methods must either have no arguments and return foo.bar.Baz or have one"
                + " argument and return foo.bar.Baz.Builder")
        .in(javaFileObject).onLine(11);
  }

  public void testRetroFacebookBuilderMissingBuildMethod() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz<T> {",
        "  abstract T blam();",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder<T> {",
        "    Builder<T> blam(T x);",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining(
            "Builder must have a single no-argument method returning foo.bar.Baz<T>")
        .in(javaFileObject).onLine(10);
  }

  public void testRetroFacebookBuilderDuplicateBuildMethods() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  abstract String blam();",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder {",
        "    Builder blam(String x);",
        "    Baz build();",
        "    Baz create();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("Builder must have a single no-argument method returning foo.bar.Baz")
        .in(javaFileObject).onLine(12)
        .and()
        .withErrorContaining("Builder must have a single no-argument method returning foo.bar.Baz")
        .in(javaFileObject).onLine(13);
  }

  public void testRetroFacebookBuilderWrongTypeBuildMethod() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  abstract String blam();",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder {",
        "    Builder blam(String x);",
        "    String build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("Builder must have a single no-argument method returning foo.bar.Baz")
        .in(javaFileObject).onLine(10);
  }

  public void testRetroFacebookBuilderTypeParametersDontMatch1() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz<T> {",
        "  abstract String blam();",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder {",
        "    Builder blam(String x);",
        "    Baz build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("Type parameters of foo.bar.Baz.Builder must have same names and "
            + "bounds as type parameters of foo.bar.Baz")
        .in(javaFileObject).onLine(10);
  }

  public void testRetroFacebookBuilderTypeParametersDontMatch2() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz<T> {",
        "  abstract T blam();",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder<E> {",
        "    Builder<E> blam(E x);",
        "    Baz build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("Type parameters of foo.bar.Baz.Builder must have same names and "
            + "bounds as type parameters of foo.bar.Baz")
        .in(javaFileObject).onLine(10);
  }

  public void testRetroFacebookBuilderTypeParametersDontMatch3() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz<T extends Number & Comparable<T>> {",
        "  abstract T blam();",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder<T extends Number> {",
        "    Builder<T> blam(T x);",
        "    Baz build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("Type parameters of foo.bar.Baz.Builder must have same names and "
            + "bounds as type parameters of foo.bar.Baz")
        .in(javaFileObject).onLine(10);
  }

  public void testRetroFacebookBuilderToBuilderWrongTypeParameters() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "abstract class Baz<K extends Comparable<K>, V> {",
        "  abstract K key();",
        "  abstract V value();",
        "  abstract Builder<V, K> toBuilder1();",
        "",
        "  @RetroFacebook.Builder",
        "  interface Builder<K extends Comparable<K>, V> {",
        "    Builder<K, V> key(K key);",
        "    Builder<K, V> value(V value);",
        "    Baz<K, V> build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("Builder converter method should return foo.bar.Baz.Builder<K, V>")
        .in(javaFileObject).onLine(9);
  }

  public void testRetroFacebookBuilderToBuilderDuplicate() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "abstract class Baz<K extends Comparable<K>, V> {",
        "  abstract K key();",
        "  abstract V value();",
        "  abstract Builder<K, V> toBuilder1();",
        "  abstract Builder<K, V> toBuilder2();",
        "",
        "  @RetroFacebook.Builder",
        "  interface Builder<K extends Comparable<K>, V> {",
        "    Builder<K, V> key(K key);",
        "    Builder<K, V> value(V value);",
        "    Baz<K, V> build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("There can be at most one builder converter method")
        .in(javaFileObject).onLine(9);
  }

  public void testRetroFacebookValidateNotInRetroFacebook() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "public abstract class Baz {",
        "  abstract String blam();",
        "",
        "  @RetroFacebook.Validate",
        "  void validate() {}",
        "",
        "  public interface Builder {",
        "    Builder blam(String x);",
        "    Baz build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining(
            "@RetroFacebook.Validate can only be applied to a method inside an @RetroFacebook class")
        .in(javaFileObject).onLine(9);
  }

  public void testRetroFacebookValidateWithoutBuilder() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  abstract String blam();",
        "",
        "  @RetroFacebook.Validate",
        "  void validate() {}",
        "",
        "  public interface Builder {",
        "    Builder blam(String x);",
        "    Baz build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining(
            "@RetroFacebook.Validate is only meaningful if there is an @RetroFacebook.Builder")
        .in(javaFileObject).onLine(10);
  }

  public void testRetroFacebookBuilderValidateMethodStatic() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  abstract String blam();",
        "",
        "  @RetroFacebook.Validate",
        "  static void validate() {}",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder {",
        "    Builder blam(String x);",
        "    Baz build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("@RetroFacebook.Validate cannot apply to a static method")
        .in(javaFileObject).onLine(10);
  }

  public void testRetroFacebookBuilderValidateMethodNotVoid() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  abstract String blam();",
        "",
        "  @RetroFacebook.Validate",
        "  Baz validate() {",
        "    return this;",
        "  }",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder {",
        "    Builder blam(String x);",
        "    Baz build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("@RetroFacebook.Validate method must be void")
        .in(javaFileObject).onLine(10);
  }

  public void testRetroFacebookBuilderValidateMethodWithParameters() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  abstract String blam();",
        "",
        "  @RetroFacebook.Validate",
        "  void validate(boolean why) {}",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder {",
        "    Builder blam(String x);",
        "    Baz build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("@RetroFacebook.Validate method must not have parameters")
        .in(javaFileObject).onLine(10);
  }

  public void testRetroFacebookBuilderValidateMethodDuplicate() {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  abstract String blam();",
        "",
        "  @RetroFacebook.Validate",
        "  void validate() {}",
        "",
        "  @RetroFacebook.Validate",
        "  void validateSomeMore() {}",
        "",
        "  @RetroFacebook.Builder",
        "  public interface Builder {",
        "    Builder blam(String x);",
        "    Baz build();",
        "  }",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor(), new RetroFacebookBuilderProcessor())
        .failsToCompile()
        .withErrorContaining("There can only be one @RetroFacebook.Validate method")
        .in(javaFileObject).onLine(13);
  }

  public void testGetFooIsFoo() throws Exception {
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  abstract int getFoo();",
        "  abstract boolean isFoo();",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new RetroFacebookProcessor())
        .failsToCompile()
        .withErrorContaining("More than one @RetroFacebook property called foo")
        .in(javaFileObject).onLine(8);
  }

  private static class PoisonedRetroFacebookProcessor extends RetroFacebookProcessor {
    private final IllegalArgumentException filerException;

    PoisonedRetroFacebookProcessor(IllegalArgumentException filerException) {
      this.filerException = filerException;
    }

    private class ErrorInvocationHandler implements InvocationHandler {
      private final ProcessingEnvironment originalProcessingEnv;

      ErrorInvocationHandler(ProcessingEnvironment originalProcessingEnv) {
        this.originalProcessingEnv = originalProcessingEnv;
      }

      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (method.getName().equals("getFiler")) {
          throw filerException;
        } else {
          return method.invoke(originalProcessingEnv, args);
        }
      }
    };

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
      ProcessingEnvironment poisonedProcessingEnv = (ProcessingEnvironment) Proxy.newProxyInstance(
          getClass().getClassLoader(),
          new Class<?>[] {ProcessingEnvironment.class},
          new ErrorInvocationHandler(processingEnv));
      processingEnv = poisonedProcessingEnv;
      return super.process(annotations, roundEnv);
    }
  }

  public void testExceptionBecomesError() throws Exception {
    // Ensure that if the annotation processor code gets an unexpected exception, it is converted
    // into a compiler error rather than being propagated. Otherwise the output can be very
    // confusing to the user who stumbles into a bug that causes an exception, whether in
    // RetroFacebookProcessor or javac.
    // We inject an exception by subclassing RetroFacebookProcessor in order to poison its processingEnv
    // in a way that will cause an exception the first time it tries to get the Filer.
    IllegalArgumentException exception =
        new IllegalArgumentException("I don't understand the question, and I won't respond to it");
    JavaFileObject javaFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  public abstract int foo();",
        "}");
    assertAbout(javaSource())
        .that(javaFileObject)
        .processedWith(new PoisonedRetroFacebookProcessor(exception))
        .failsToCompile()
        .withErrorContaining(exception.toString())
        .in(javaFileObject).onLine(6);
  }

  @Retention(RetentionPolicy.SOURCE)
  public @interface Foo {}

  /* Processor that generates an empty class BarFoo every time it sees a class Bar annotated with
   * @Foo.
   */
  public static class FooProcessor extends AbstractProcessor {
    @Override
    public Set<String> getSupportedAnnotationTypes() {
      return ImmutableSet.of(Foo.class.getCanonicalName());
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
      return SourceVersion.latestSupported();
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
      Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(Foo.class);
      for (TypeElement type : ElementFilter.typesIn(elements)) {
        try {
          generateFoo(type);
        } catch (IOException e) {
          throw new AssertionError(e);
        }
      }
      return false;
    }

    private void generateFoo(TypeElement type) throws IOException {
      String pkg = TypeSimplifier.packageNameOf(type);
      String className = type.getSimpleName().toString();
      String generatedClassName = className + "Foo";
      JavaFileObject source =
          processingEnv.getFiler().createSourceFile(pkg + "." + generatedClassName, type);
      PrintWriter writer = new PrintWriter(source.openWriter());
      writer.println("package " + pkg + ";");
      writer.println("public class " + generatedClassName + " {}");
      writer.close();
    }
  }

  public void testReferencingGeneratedClass() {
    // Test that ensures that a type that does not exist can be the type of an @RetroFacebook property
    // as long as it later does come into existence. The BarFoo type referenced here does not exist
    // when the RetroFacebookProcessor runs on the first round, but the FooProcessor then generates it.
    // That generation provokes a further round of annotation processing and RetroFacebookProcessor
    // should succeed then.
    JavaFileObject bazFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Baz",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@RetroFacebook",
        "public abstract class Baz {",
        "  public abstract BarFoo barFoo();",
        "",
        "  public static Baz create(BarFoo barFoo) {",
        "    return new RetroFacebook_Baz(barFoo);",
        "  }",
        "}");
    JavaFileObject barFileObject = JavaFileObjects.forSourceLines(
        "foo.bar.Bar",
        "package foo.bar;",
        "",
        "import retrofacebook.RetroFacebook;",
        "",
        "@" + Foo.class.getCanonicalName(),
        "public abstract class Bar {",
        "  public abstract BarFoo barFoo();",
        "}");
    assertAbout(javaSources())
        .that(ImmutableList.of(bazFileObject, barFileObject))
        .processedWith(new RetroFacebookProcessor(), new FooProcessor())
        .compilesWithoutError();
  }
}


text:
import { TextlintFilterRuleContext, TextlintRuleReportHandler } from "@textlint/types";

export default function (context: TextlintFilterRuleContext): TextlintRuleReportHandler {
    return {
        [context.Syntax.Str](node) {
            context.shouldIgnore(node.range, {});
        }
    };
}


text:
require "test_helper"

class MissMarple::SearcherTest < MiniTest::Unit::TestCase
  def test_should_search_files
    searcher = MissMarple::Searcher.search(["test/fixtures"])

    assert { searcher.class == Array }
    assert { !searcher.empty? }
  end
end


text:
$(document).ready(function(){
  $('a.ooyala-embed').click(function(event){
      if(event.preventDefault) event.preventDefault();
      else event.returnValue = false;

      var error = $("
Please enable Javascript to watch this video
");

      if ($(this).attr('data-embed')) {
			  var code = $(this).attr('data-embed');
		  } else {
			  var code = $($(this).parent().find("input")).val();
		  }

      if($.browser.msie){
        var video = document.getElementById("video");
        video.setAttribute("rel", code);
      }else{
        $("#video").attr('data-embed', code);
      }

      if($.type(OO) == 'object'){
        OO.ready(function(){
          var videoPlayer = OO.Player.create('ooyalaplayer', code, {
            autoplay: true,
            onCreate: function(player){
                window.mb = player.mb;
            }
          });

          window.mb.subscribe(OO.EVENTS.PLAYED, 'Video', function(eventName){
              $("#tranny").trigger('click');
          });

          window.mb.subscribe(OO.EVENTS.ERROR, 'Video', function(error){
              $("#tranny").trigger('click');
              _gaq.push(['_trackEvent', 'Error', error , 'Ooyala','',true]);
          });

          $("#video").fadeIn('fast');
    		  $('#tranny').fadeIn('fast');

          $('#tranny').click(function() {
            $('#tranny').fadeOut('fast').delay(150);
            $("#video").fadeOut('fast');
            videoPlayer.destroy('ooyalaplayer');
            return false;
          });

          $(document).bind('keyup', function(event) {
            if (event.keyCode == 27) {
              $("#tranny").trigger('click');
            }
            return false;
          });
        });
      }else{
        $("#video").append(error);
        _gaq.push(['_trackEvent', 'Error', 'OO Object Not Available!', 'Ooyala','',true]);
      }
  return false;
  });

  $(".sermon-embed").each(function(){
      if ($(this).attr('data-embed')) {
			  var code = $(this).attr('data-embed');
		  } else {
			  var code = $($(this).parent().find("input")).val();
		  }

      if($.browser.msie){
        var video = document.getElementById("video");
        video.setAttribute("rel", code);
      }else{
        $("#video").attr('data-embed', code);
      }

      if($.type(OO) == 'object'){
          OO.ready(function(){
            var videoPlayer = OO.Player.create('ooyalaplayer', code, {
              autoplay: false,
              onCreate: function(player){
                  window.mb = player.mb;
              }
            });

            window.mb.subscribe(OO.EVENTS.ERROR, 'Video Error', function(error){
              _gaq.push(['_trackEvent', 'Error', error , 'Ooyala','',true]);
            });

          });
        }else{
        $("#video").append(error);
        _gaq.push(['_trackEvent', 'Error', 'OO Object Not Available!', 'Ooyala','',true]);
        }

  });

  if ( (window.location.hash != '') && (!Modernizr.touch) ) {
		var hash = window.location.hash;
		$(hash + " a").trigger('click');
	}
});


text:
/**
 * @file USBMessageHandler.h
 * @author Junaith Ahemed Shahabdeen
 *
 * This file provides a higher level USB Message
 * parser and assembler. The message from the
 * USB driver is identified by its message type
 * and the required modules are invoked based on
 * the type.
 */
#ifndef USB_MESSAGE_HANDLER_H
#define USB_MESSAGE_HANDLER_H

#include <MessageDefines.h>

/**
 * Command_Packet_Received
 *
 * The function is signalled when a command packet is received
 * from the device. The function parses the USB payload
 * to determine the command type and calls the required module
 * based on the type.
 *
 * @param data USB Payload.
 *
 * @return SUCCESS | FAIL
 */
result_t Command_Packet_Received (char* data);

/**
 * Error_Packet_Received
 *
 * Received an error from the Device.
 *
 * @param data  Valid usb data.
 * @return SUCCESS | FAIL
 */
result_t Error_Packet_Received (uint8_t* data);

/**
 * Binary_Packet_Received
 *
 * Binary data received from the mote. Currently the mote sends
 * a binary packet only when the pc requests a flash dump or a
 * buffer dump.
 *
 * @param data Binary data from the mote.
 * @param length Length of the data.
 * @param seq Sequence number from the packet.
 */
result_t Binary_Packet_Received (char* data, uint8_t length, uint32_t seq);

/**
 * Dump_From_Flash
 *
 * Request a data chunk from the flash, the length of the
 * chunk and the flash address is passed as parameter to
 * the function. This function basically triggers a request
 * response cycle between the MOTE and the PC Application till
 * the entire chunk is downloaded.
 *
 * @param addr Start address of the chunk in flash.
 * @param length The size of the chunk.
 *
 * @return SUCCESS | FAIL
 */
result_t Dump_From_Flash (uint32_t addr, uint32_t length);

/**
 * Get_Buffer_Dump
 *
 * The function requests the next packet from the IMote during
 * flash dump mode. The process continues till the window size
 * and is trigerred by the <I>Dump_From_Flash</I> function
 * for the next buffer.
 *
 * @return SUCESS | FAIL
 */
result_t Get_Buffer_Dump ();

/**
 * Send_USB_Command
 *
 * Send a command message to the Mote.
 *
 * @param cmd Command struct with appropriate data defined in MessageDefines.h.
 * @param length Length of the command data.
 *
 * @return SUCCESS | FAIL
 */
result_t Send_USB_Command (USBCommand* cmd, uint32_t Length);

/**
 * Send_USB_Command_Packet
 *
 * Send a command message to the Mote.
 *
 * @param cmd Command type defined in the enum (see MessageDefines.h).
 * @param clen Length of the command data.
 * @param cdata Command data in array format.
 *
 * @return SUCCESS | FAIL
 */
result_t Send_USB_Command_Packet (Commands cmd, uint8_t clen, void* cdata);

/**
 * Send_Binary_Data
 *
 * Send a binary buffer to the device. Usually binary data is prepended
 * with the sequence number of the packet the final packet will
 * have a sequence number of 0. JT Protocol requires a header with the
 * valid bytes in the packet if the seqence number is 0, this allows
 * the pc host to send less than IMOTE_HID_TYPE_L_SHORT in the last
 * packet if required.
 *
 * @param buff Pointer to the binary buffer.
 * @param length Length of the buffer.
 * @param seq Current Sequence number of the buffer.
 *
 * @return SUCCESS | FAIL
 */
result_t Send_Binary_Data (uint8_t* buff, uint32_t Length, uint16_t seq);

/**
 * Send_USB_Binary_Data
 *
 * The function allows the user to send binary data packed in
 * a structure.
 *
 * @param img The struct which contains binary data.
 * @param length length of the struct with data.
 *
 * @return SUCCESS | FAIL
 */
result_t Send_USB_Binary_Data (USBImagePck* img, uint32_t Length);

//#ifdef DEBUG
/**
 * Dbg_Binary_Code_Upload
 *
 * Function used in the -tp option to send the
 * image detail command to the device.
 *
 * @return SUCCESS | FAIL
 */
result_t Dbg_Binary_Code_Upload ();
//#endif

#endif


text:
package org.devspark.aws.lambdasupport.endpoint;

import java.util.function.Function;

public class ActionRegistryEntry {
    private final String action;
    private final Class<?> payloadClass;
    private final Function<Object, ?> handle;

    public ActionRegistryEntry(String action, Class<?> payloadClass,
            Function<Object, ?> handle) {
        super();
        this.action = action;
        this.payloadClass = payloadClass;
        this.handle = handle;
    }

    public String getAction() {
        return action;
    }

    public Class<?> getPayloadClass() {
        return payloadClass;
    }

    public Function<Object, ?> getHandle() {
        return handle;
    }
}


text:
{% extends 'skeleton.html' %}

{% block page_class %}Programs{% endblock %}

{% block content %}

Programs

	{% if programs %}

	    {% for program in programs %}

{{ program.title }}

	    {% endfor %}

	{% else %}

No programs are available.

	{% endif %}
{% endblock %}


text:
// Copyright 2015 Satoshi Konno. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
Config loads JSON files which has comments.

Config gets a setting value in the specified file by the given path like Path.

	config, err := NewConfig()
	if err != nil {
		t.Error(err)
	}

	err = config.ParseFromFile("/etc/profile.conf")
	if err != nil {
		t.Error(err)
	}

	name, err := config.GetKeyStringByPath("/organizer/name")
	if err != nil {
		t.Error(err)
	}

	age, err := config.GetKeyStringByPath("/organizer/age")
	if err != nil {
		t.Error(err)
	}

The configuration file fomat is based on JSON as the following.

	#
	#  /etc/profile.conf
	#

	{
		"organizer": {
			"name": "John Smith",
			"age": 33
		}
	}
*/
package config

import (
	"bytes"
	"strings"
)

const (
	Comment = "#"
)

type Config struct {
	Parser
}

// NewConfig returns a new Config.
func NewConfig() (*Config, error) {
	config := &Config{}
	return config, nil
}

// NewConfigFromFile returns a new Config from the given file.
func NewConfigFromFile(file string) (*Config, error) {
	config := &Config{}
	err := config.ParseFromFile(file)
	if err != nil {
		return nil, err
	}
	return config, nil
}

// NewConfigFromString returns a new Config from the given string.
func NewConfigFromString(s string) (*Config, error) {
	config := &Config{}
	err := config.ParseFromString(s)
	if err != nil {
		return nil, err
	}
	return config, nil
}

// ParseFromString parses the given string.
func (config *Config) ParseFromString(source string) error {
	lines := strings.Split(source, LineSep)

	// Strip comment and null lines
	var strippedSource bytes.Buffer
	for _, line := range lines {
		if len(line) <= 0 {
			continue
		}
		commentIdx := strings.Index(line, Comment)
		if 0 <= commentIdx {
			continue
		}
		strippedSource.WriteString(line + LineSep)
	}

	return config.ParseFromBytes(strippedSource.Bytes())
}


text:
package net

import (
	"fmt"
	"net"
	"time"
)

func EnsureInterface(ifaceName string, wait int) (iface *net.Interface, err error) {
	if iface, err = findInterface(ifaceName); err == nil || wait == 0 {
		return
	}
	for ; err != nil && wait > 0; wait -= 1 {
		time.Sleep(1 * time.Second)
		iface, err = findInterface(ifaceName)
	}
	return
}

func findInterface(ifaceName string) (iface *net.Interface, err error) {
	if iface, err = net.InterfaceByName(ifaceName); err != nil {
		return iface, fmt.Errorf("Unable to find interface %s", ifaceName)
	}
	if 0 == (net.FlagUp & iface.Flags) {
		return iface, fmt.Errorf("Interface %s is not up", ifaceName)
	}
	return
}


text:
BUILD_DATE_TIME=`date`
BUILD_HOSTNAME=`hostname`
BUILD_GCC_VERSION=`gcc --version | head -n 1`

gen_info_template_header ()
{
    echo "// Generated by the build_version.sh.  DO NOT EDIT!"
    echo " "
    echo "#include <iostream>"
    echo "#include \"version.h\""
    echo "const char kGitInfo[] = \"\\"
}

gen_info_template_foot ()
{
    echo "\";"
    echo "const char kBuildTime[] = \"$BUILD_DATE_TIME\";"
    echo "const char kBuilderName[] = \"$USER\";"
    echo "const char kHostName[] = \"$BUILD_HOSTNAME\";"
}

gen_info_print_template ()
{
    echo "void PrintSystemVersion() {"
    echo "    std::cout << \"Baidu File System v\" << kMajorVersion << \".\" << kMinorVersion << \".\" << kRevision << std::endl;"
    echo "    std::cout << \"=====  Git Info ===== \" << std::endl;"
    echo "    std::cout << kGitInfo << std::endl;"
    echo "    std::cout << \"=====  Build Info ===== \" << std::endl;"
    echo "    std::cout << \"Build Time: \" << kBuildTime << std::endl;"
    echo "    std::cout << \"Builder Name: \" << kBuilderName << std::endl;"
    echo "    std::cout << \"Build Host Name: \" << kHostName << std::endl;"
    echo "    std::cout << \"Build Compiler: \" << kCompiler << std::endl;"
    echo "    std::cout << std::endl;"
    echo "};"
}

TEMPLATE_HEADER_FILE=template_header.tmp
TEMPLATE_FOOT_FILE=template_foot.tmp
GIT_INFO_FILE=git_info.tmp
VERSION_CPP_FILE=src/version.cc

# generate template file
git remote -v | sed 's/$/&\\n\\/g' > $GIT_INFO_FILE
git log | head -n 3 | sed 's/$/&\\n\\/g' >> $GIT_INFO_FILE
gen_info_template_header > $TEMPLATE_HEADER_FILE
gen_info_template_foot > $TEMPLATE_FOOT_FILE
gen_info_print_template >> $TEMPLATE_FOOT_FILE

# generate version cpp
cat $TEMPLATE_HEADER_FILE $GIT_INFO_FILE $TEMPLATE_FOOT_FILE > $VERSION_CPP_FILE
rm -rf $TEMPLATE_HEADER_FILE $GIT_INFO_FILE $TEMPLATE_FOOT_FILE


text:
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Newtonsoft.Json;
using Reusable.Data;
using Reusable.OmniLog.Abstractions;

namespace Reusable.Flexo
{
    [PublicAPI]
    public abstract class Comparer : ValueExtension<bool>
    {
        private readonly Func<int, bool> _predicate;

        protected Comparer(ILogger logger, string name, [NotNull] Func<int, bool> predicate)
            : base(logger, name) => _predicate = predicate;

        [JsonProperty("Left")]
        public override IExpression This { get; set; }

        [JsonRequired]
        [JsonProperty("Value")]
        public IExpression Right { get; set; }

        protected override Constant<bool> InvokeCore(IExpression @this)
        {
            var result = Comparer<object>.Default.Compare(@this.Invoke().Value, Right.Invoke().Value);
            return (Name, _predicate(result));
        }
    }
}