text: #include <cstring>
  #include <string>
  #include <vector>
  
  #include "google/protobuf/text_format.h"
  #include "gtest/gtest.h"
  
  #include "caffe/blob.hpp"
  #include "caffe/common.hpp"
  #include "caffe/layer.hpp"
  #include "caffe/util/upgrade_proto.hpp"
  
  #include "caffe/test/test_caffe_main.hpp"
  
  namespace caffe {
  
  class PaddingLayerUpgradeTest : public ::testing::Test {
   protected:
    void RunPaddingUpgradeTest(
        const string& input_param_string, const string& output_param_string) {
      // Test that UpgradeV0PaddingLayers called on the proto specified by
      // input_param_string results in the proto specified by
      // output_param_string.
      NetParameter input_param;
      CHECK(google::protobuf::TextFormat::ParseFromString(
          input_param_string, &input_param));
      NetParameter expected_output_param;
      CHECK(google::protobuf::TextFormat::ParseFromString(
          output_param_string, &expected_output_param));
      NetParameter actual_output_param;
      UpgradeV0PaddingLayers(input_param, &actual_output_param);
      EXPECT_EQ(expected_output_param.DebugString(),
          actual_output_param.DebugString());
      // Also test idempotence.
      NetParameter double_pad_upgrade_param;
      UpgradeV0PaddingLayers(actual_output_param, &double_pad_upgrade_param);
      EXPECT_EQ(actual_output_param.DebugString(),
         double_pad_upgrade_param.DebugString());
    }
  };
  
  TEST_F(PaddingLayerUpgradeTest, TestSimple) {
    const string& input_proto =
        "name: 'CaffeNet' "
        "layers { "
        "  layer { "
        "    name: 'data' "
        "    type: 'data' "
        "    source: '/home/jiayq/Data/ILSVRC12/train-leveldb' "
        "    meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' "
        "    batchsize: 256 "
        "    cropsize: 227 "
        "    mirror: true "
        "  } "
        "  top: 'data' "
        "  top: 'label' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pad1' "
        "    type: 'padding' "
        "    pad: 2 "
        "  } "
        "  bottom: 'data' "
        "  top: 'pad1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv1' "
        "    type: 'conv' "
        "    num_output: 96 "
        "    kernelsize: 11 "
        "    stride: 4 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'pad1' "
        "  top: 'conv1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'fc8' "
        "    type: 'innerproduct' "
        "    num_output: 1000 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0 "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'conv1' "
        "  top: 'fc8' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'loss' "
        "    type: 'softmax_loss' "
        "  } "
        "  bottom: 'fc8' "
        "  bottom: 'label' "
        "} ";
    const string& expected_output_proto =
        "name: 'CaffeNet' "
        "layers { "
        "  layer { "
        "    name: 'data' "
        "    type: 'data' "
        "    source: '/home/jiayq/Data/ILSVRC12/train-leveldb' "
        "    meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' "
        "    batchsize: 256 "
        "    cropsize: 227 "
        "    mirror: true "
        "  } "
        "  top: 'data' "
        "  top: 'label' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv1' "
        "    type: 'conv' "
        "    num_output: 96 "
        "    kernelsize: 11 "
        "    stride: 4 "
        "    pad: 2 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'data' "
        "  top: 'conv1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'fc8' "
        "    type: 'innerproduct' "
        "    num_output: 1000 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0 "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'conv1' "
        "  top: 'fc8' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'loss' "
        "    type: 'softmax_loss' "
        "  } "
        "  bottom: 'fc8' "
        "  bottom: 'label' "
        "} ";
    this->RunPaddingUpgradeTest(input_proto, expected_output_proto);
  }
  
  TEST_F(PaddingLayerUpgradeTest, TestTwoTops) {
    const string& input_proto =
        "name: 'CaffeNet' "
        "layers { "
        "  layer { "
        "    name: 'data' "
        "    type: 'data' "
        "    source: '/home/jiayq/Data/ILSVRC12/train-leveldb' "
        "    meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' "
        "    batchsize: 256 "
        "    cropsize: 227 "
        "    mirror: true "
        "  } "
        "  top: 'data' "
        "  top: 'label' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pad1' "
        "    type: 'padding' "
        "    pad: 2 "
        "  } "
        "  bottom: 'data' "
        "  top: 'pad1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv1' "
        "    type: 'conv' "
        "    num_output: 96 "
        "    kernelsize: 11 "
        "    stride: 4 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'pad1' "
        "  top: 'conv1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'fc8' "
        "    type: 'innerproduct' "
        "    num_output: 1000 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0 "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'conv1' "
        "  top: 'fc8' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv2' "
        "    type: 'conv' "
        "    num_output: 96 "
        "    kernelsize: 11 "
        "    stride: 4 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'pad1' "
        "  top: 'conv2' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'loss' "
        "    type: 'softmax_loss' "
        "  } "
        "  bottom: 'fc8' "
        "  bottom: 'label' "
        "} ";
    const string& expected_output_proto =
        "name: 'CaffeNet' "
        "layers { "
        "  layer { "
        "    name: 'data' "
        "    type: 'data' "
        "    source: '/home/jiayq/Data/ILSVRC12/train-leveldb' "
        "    meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' "
        "    batchsize: 256 "
        "    cropsize: 227 "
        "    mirror: true "
        "  } "
        "  top: 'data' "
        "  top: 'label' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv1' "
        "    type: 'conv' "
        "    num_output: 96 "
        "    kernelsize: 11 "
        "    stride: 4 "
        "    pad: 2 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'data' "
        "  top: 'conv1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'fc8' "
        "    type: 'innerproduct' "
        "    num_output: 1000 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0 "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'conv1' "
        "  top: 'fc8' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv2' "
        "    type: 'conv' "
        "    num_output: 96 "
        "    kernelsize: 11 "
        "    stride: 4 "
        "    pad: 2 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'data' "
        "  top: 'conv2' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'loss' "
        "    type: 'softmax_loss' "
        "  } "
        "  bottom: 'fc8' "
        "  bottom: 'label' "
        "} ";
    this->RunPaddingUpgradeTest(input_proto, expected_output_proto);
  }
  
  TEST_F(PaddingLayerUpgradeTest, TestImageNet) {
    const string& input_proto =
        "name: 'CaffeNet' "
        "layers { "
        "  layer { "
        "    name: 'data' "
        "    type: 'data' "
        "    source: '/home/jiayq/Data/ILSVRC12/train-leveldb' "
        "    meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' "
        "    batchsize: 256 "
        "    cropsize: 227 "
        "    mirror: true "
        "  } "
        "  top: 'data' "
        "  top: 'label' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv1' "
        "    type: 'conv' "
        "    num_output: 96 "
        "    kernelsize: 11 "
        "    stride: 4 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'data' "
        "  top: 'conv1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu1' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'conv1' "
        "  top: 'conv1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pool1' "
        "    type: 'pool' "
        "    pool: MAX "
        "    kernelsize: 3 "
        "    stride: 2 "
        "  } "
        "  bottom: 'conv1' "
        "  top: 'pool1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'norm1' "
        "    type: 'lrn' "
        "    local_size: 5 "
        "    alpha: 0.0001 "
        "    beta: 0.75 "
        "  } "
        "  bottom: 'pool1' "
        "  top: 'norm1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pad2' "
        "    type: 'padding' "
        "    pad: 2 "
        "  } "
        "  bottom: 'norm1' "
        "  top: 'pad2' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv2' "
        "    type: 'conv' "
        "    num_output: 256 "
        "    group: 2 "
        "    kernelsize: 5 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'pad2' "
        "  top: 'conv2' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu2' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'conv2' "
        "  top: 'conv2' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pool2' "
        "    type: 'pool' "
        "    pool: MAX "
        "    kernelsize: 3 "
        "    stride: 2 "
        "  } "
        "  bottom: 'conv2' "
        "  top: 'pool2' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'norm2' "
        "    type: 'lrn' "
        "    local_size: 5 "
        "    alpha: 0.0001 "
        "    beta: 0.75 "
        "  } "
        "  bottom: 'pool2' "
        "  top: 'norm2' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pad3' "
        "    type: 'padding' "
        "    pad: 1 "
        "  } "
        "  bottom: 'norm2' "
        "  top: 'pad3' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv3' "
        "    type: 'conv' "
        "    num_output: 384 "
        "    kernelsize: 3 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'pad3' "
        "  top: 'conv3' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu3' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'conv3' "
        "  top: 'conv3' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pad4' "
        "    type: 'padding' "
        "    pad: 1 "
        "  } "
        "  bottom: 'conv3' "
        "  top: 'pad4' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv4' "
        "    type: 'conv' "
        "    num_output: 384 "
        "    group: 2 "
        "    kernelsize: 3 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'pad4' "
        "  top: 'conv4' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu4' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'conv4' "
        "  top: 'conv4' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pad5' "
        "    type: 'padding' "
        "    pad: 1 "
        "  } "
        "  bottom: 'conv4' "
        "  top: 'pad5' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv5' "
        "    type: 'conv' "
        "    num_output: 256 "
        "    group: 2 "
        "    kernelsize: 3 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'pad5' "
        "  top: 'conv5' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu5' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'conv5' "
        "  top: 'conv5' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pool5' "
        "    type: 'pool' "
        "    kernelsize: 3 "
        "    pool: MAX "
        "    stride: 2 "
        "  } "
        "  bottom: 'conv5' "
        "  top: 'pool5' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'fc6' "
        "    type: 'innerproduct' "
        "    num_output: 4096 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.005 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'pool5' "
        "  top: 'fc6' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu6' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'fc6' "
        "  top: 'fc6' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'drop6' "
        "    type: 'dropout' "
        "    dropout_ratio: 0.5 "
        "  } "
        "  bottom: 'fc6' "
        "  top: 'fc6' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'fc7' "
        "    type: 'innerproduct' "
        "    num_output: 4096 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.005 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'fc6' "
        "  top: 'fc7' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu7' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'fc7' "
        "  top: 'fc7' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'drop7' "
        "    type: 'dropout' "
        "    dropout_ratio: 0.5 "
        "  } "
        "  bottom: 'fc7' "
        "  top: 'fc7' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'fc8' "
        "    type: 'innerproduct' "
        "    num_output: 1000 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0 "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'fc7' "
        "  top: 'fc8' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'loss' "
        "    type: 'softmax_loss' "
        "  } "
        "  bottom: 'fc8' "
        "  bottom: 'label' "
        "} ";
    const string& expected_output_proto =
        "name: 'CaffeNet' "
        "layers { "
        "  layer { "
        "    name: 'data' "
        "    type: 'data' "
        "    source: '/home/jiayq/Data/ILSVRC12/train-leveldb' "
        "    meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' "
        "    batchsize: 256 "
        "    cropsize: 227 "
        "    mirror: true "
        "  } "
        "  top: 'data' "
        "  top: 'label' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv1' "
        "    type: 'conv' "
        "    num_output: 96 "
        "    kernelsize: 11 "
        "    stride: 4 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'data' "
        "  top: 'conv1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu1' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'conv1' "
        "  top: 'conv1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pool1' "
        "    type: 'pool' "
        "    pool: MAX "
        "    kernelsize: 3 "
        "    stride: 2 "
        "  } "
        "  bottom: 'conv1' "
        "  top: 'pool1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'norm1' "
        "    type: 'lrn' "
        "    local_size: 5 "
        "    alpha: 0.0001 "
        "    beta: 0.75 "
        "  } "
        "  bottom: 'pool1' "
        "  top: 'norm1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv2' "
        "    type: 'conv' "
        "    num_output: 256 "
        "    group: 2 "
        "    kernelsize: 5 "
        "    pad: 2 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'norm1' "
        "  top: 'conv2' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu2' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'conv2' "
        "  top: 'conv2' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pool2' "
        "    type: 'pool' "
        "    pool: MAX "
        "    kernelsize: 3 "
        "    stride: 2 "
        "  } "
        "  bottom: 'conv2' "
        "  top: 'pool2' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'norm2' "
        "    type: 'lrn' "
        "    local_size: 5 "
        "    alpha: 0.0001 "
        "    beta: 0.75 "
        "  } "
        "  bottom: 'pool2' "
        "  top: 'norm2' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv3' "
        "    type: 'conv' "
        "    num_output: 384 "
        "    kernelsize: 3 "
        "    pad: 1 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'norm2' "
        "  top: 'conv3' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu3' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'conv3' "
        "  top: 'conv3' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv4' "
        "    type: 'conv' "
        "    num_output: 384 "
        "    group: 2 "
        "    kernelsize: 3 "
        "    pad: 1 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'conv3' "
        "  top: 'conv4' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu4' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'conv4' "
        "  top: 'conv4' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv5' "
        "    type: 'conv' "
        "    num_output: 256 "
        "    group: 2 "
        "    kernelsize: 3 "
        "    pad: 1 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'conv4' "
        "  top: 'conv5' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu5' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'conv5' "
        "  top: 'conv5' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pool5' "
        "    type: 'pool' "
        "    kernelsize: 3 "
        "    pool: MAX "
        "    stride: 2 "
        "  } "
        "  bottom: 'conv5' "
        "  top: 'pool5' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'fc6' "
        "    type: 'innerproduct' "
        "    num_output: 4096 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.005 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'pool5' "
        "  top: 'fc6' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu6' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'fc6' "
        "  top: 'fc6' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'drop6' "
        "    type: 'dropout' "
        "    dropout_ratio: 0.5 "
        "  } "
        "  bottom: 'fc6' "
        "  top: 'fc6' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'fc7' "
        "    type: 'innerproduct' "
        "    num_output: 4096 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.005 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'fc6' "
        "  top: 'fc7' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu7' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'fc7' "
        "  top: 'fc7' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'drop7' "
        "    type: 'dropout' "
        "    dropout_ratio: 0.5 "
        "  } "
        "  bottom: 'fc7' "
        "  top: 'fc7' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'fc8' "
        "    type: 'innerproduct' "
        "    num_output: 1000 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0 "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'fc7' "
        "  top: 'fc8' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'loss' "
        "    type: 'softmax_loss' "
        "  } "
        "  bottom: 'fc8' "
        "  bottom: 'label' "
        "} ";
    this->RunPaddingUpgradeTest(input_proto, expected_output_proto);
  }
  
  class NetUpgradeTest : public ::testing::Test {
   protected:
    void RunV0UpgradeTest(
        const string& input_param_string, const string& output_param_string) {
      // Test that UpgradeV0Net called on the NetParameter proto specified by
      // input_param_string results in the NetParameter proto specified by
      // output_param_string.
      NetParameter input_param;
      CHECK(google::protobuf::TextFormat::ParseFromString(
          input_param_string, &input_param));
      NetParameter expected_output_param;
      CHECK(google::protobuf::TextFormat::ParseFromString(
          output_param_string, &expected_output_param));
      NetParameter actual_output_param;
      UpgradeV0Net(input_param, &actual_output_param);
      EXPECT_EQ(expected_output_param.DebugString(),
          actual_output_param.DebugString());
    }
  
    void RunV1UpgradeTest(
        const string& input_param_string, const string& output_param_string) {
      // Test that UpgradeV0Net called on the NetParameter proto specified by
      // input_param_string results in the NetParameter proto specified by
      // output_param_string.
      NetParameter input_param;
      CHECK(google::protobuf::TextFormat::ParseFromString(
          input_param_string, &input_param));
      NetParameter expected_output_param;
      CHECK(google::protobuf::TextFormat::ParseFromString(
          output_param_string, &expected_output_param));
      NetParameter actual_output_param;
      UpgradeV1Net(input_param, &actual_output_param);
      EXPECT_EQ(expected_output_param.DebugString(),
          actual_output_param.DebugString());
    }
  };
  
  TEST_F(NetUpgradeTest, TestSimple) {
    const string& v0_proto =
        "name: 'CaffeNet' "
        "layers { "
        "  layer { "
        "    name: 'data' "
        "    type: 'data' "
        "    source: '/home/jiayq/Data/ILSVRC12/train-leveldb' "
        "    meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' "
        "    batchsize: 256 "
        "    cropsize: 227 "
        "    mirror: true "
        "  } "
        "  top: 'data' "
        "  top: 'label' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pad1' "
        "    type: 'padding' "
        "    pad: 2 "
        "  } "
        "  bottom: 'data' "
        "  top: 'pad1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv1' "
        "    type: 'conv' "
        "    num_output: 96 "
        "    kernelsize: 11 "
        "    stride: 4 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'pad1' "
        "  top: 'conv1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'fc8' "
        "    type: 'innerproduct' "
        "    num_output: 1000 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0 "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'conv1' "
        "  top: 'fc8' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'loss' "
        "    type: 'softmax_loss' "
        "  } "
        "  bottom: 'fc8' "
        "  bottom: 'label' "
        "} ";
    const string& expected_v1_proto =
        "name: 'CaffeNet' "
        "layers { "
        "  name: 'data' "
        "  type: DATA "
        "  data_param { "
        "    source: '/home/jiayq/Data/ILSVRC12/train-leveldb' "
        "    batch_size: 256 "
        "  } "
        "  transform_param { "
        "    crop_size: 227 "
        "    mirror: true "
        "    mean_file: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' "
        "  } "
        "  top: 'data' "
        "  top: 'label' "
        "} "
        "layers { "
        "  name: 'conv1' "
        "  type: CONVOLUTION "
        "  convolution_param { "
        "    num_output: 96 "
        "    kernel_size: 11 "
        "    stride: 4 "
        "    pad: 2 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "  } "
        "  blobs_lr: 1. "
        "  blobs_lr: 2. "
        "  weight_decay: 1. "
        "  weight_decay: 0. "
        "  bottom: 'data' "
        "  top: 'conv1' "
        "} "
        "layers { "
        "  name: 'fc8' "
        "  type: INNER_PRODUCT "
        "  inner_product_param { "
        "    num_output: 1000 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0 "
        "    } "
        "  } "
        "  blobs_lr: 1. "
        "  blobs_lr: 2. "
        "  weight_decay: 1. "
        "  weight_decay: 0. "
        "  bottom: 'conv1' "
        "  top: 'fc8' "
        "} "
        "layers { "
        "  name: 'loss' "
        "  type: SOFTMAX_LOSS "
        "  bottom: 'fc8' "
        "  bottom: 'label' "
        "} ";
    this->RunV0UpgradeTest(v0_proto, expected_v1_proto);
  
    const string& expected_v2_proto =
        "name: 'CaffeNet' "
        "layer { "
        "  name: 'data' "
        "  type: 'Data' "
        "  data_param { "
        "    source: '/home/jiayq/Data/ILSVRC12/train-leveldb' "
        "    batch_size: 256 "
        "  } "
        "  transform_param { "
        "    crop_size: 227 "
        "    mirror: true "
        "    mean_file: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' "
        "  } "
        "  top: 'data' "
        "  top: 'label' "
        "} "
        "layer { "
        "  name: 'conv1' "
        "  type: 'Convolution' "
        "  convolution_param { "
        "    num_output: 96 "
        "    kernel_size: 11 "
        "    stride: 4 "
        "    pad: 2 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "  } "
        "  param { "
        "    lr_mult: 1 "
        "    decay_mult: 1 "
        "  } "
        "  param { "
        "    lr_mult: 2 "
        "    decay_mult: 0 "
        "  } "
        "  bottom: 'data' "
        "  top: 'conv1' "
        "} "
        "layer { "
        "  name: 'fc8' "
        "  type: 'InnerProduct' "
        "  inner_product_param { "
        "    num_output: 1000 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0 "
        "    } "
        "  } "
        "  param { "
        "    lr_mult: 1 "
        "    decay_mult: 1 "
        "  } "
        "  param { "
        "    lr_mult: 2 "
        "    decay_mult: 0 "
        "  } "
        "  bottom: 'conv1' "
        "  top: 'fc8' "
        "} "
        "layer { "
        "  name: 'loss' "
        "  type: 'SoftmaxWithLoss' "
        "  bottom: 'fc8' "
        "  bottom: 'label' "
        "} ";
    this->RunV1UpgradeTest(expected_v1_proto, expected_v2_proto);
  }
  
  // Test any layer or parameter upgrades not covered by other tests.
  TEST_F(NetUpgradeTest, TestAllParams) {
    const string& input_proto =
        "name: 'CaffeNet' "
        "input: 'input_data' "
        "input_dim: 64 "
        "input_dim: 3 "
        "input_dim: 32 "
        "input_dim: 32 "
        "layers { "
        "  layer { "
        "    name: 'data' "
        "    type: 'data' "
        "    source: '/home/jiayq/Data/ILSVRC12/train-leveldb' "
        "    meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' "
        "    batchsize: 256 "
        "    cropsize: 227 "
        "    mirror: true "
        "    scale: 0.25 "
        "    rand_skip: 73 "
        "  } "
        "  top: 'data' "
        "  top: 'label' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'images' "
        "    type: 'images' "
        "    source: '/home/jiayq/Data/ILSVRC12/train-images' "
        "    meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' "
        "    batchsize: 256 "
        "    cropsize: 227 "
        "    mirror: true "
        "    scale: 0.25 "
        "    rand_skip: 73 "
        "    shuffle_images: true "
        "    new_height: 40 "
        "    new_width: 30 "
        "  } "
        "  top: 'images_data' "
        "  top: 'images_label' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'window_data' "
        "    type: 'window_data' "
        "    source: '/home/jiayq/Data/ILSVRC12/train-leveldb' "
        "    meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' "
        "    batchsize: 256 "
        "    cropsize: 227 "
        "    mirror: true "
        "    det_fg_threshold: 0.25 "
        "    det_bg_threshold: 0.75 "
        "    det_fg_fraction: 0.5 "
        "    det_context_pad: 16 "
        "    det_crop_mode: 'square' "
        "  } "
        "  top: 'window_data' "
        "  top: 'window_label' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'hdf5data' "
        "    type: 'hdf5_data' "
        "    source: '/my/hdf5/data' "
        "    batchsize: 256 "
        "  } "
        "  top: 'hdf5data' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv1' "
        "    type: 'conv' "
        "    num_output: 96 "
        "    biasterm: false "
        "    pad: 4 "
        "    kernelsize: 11 "
        "    stride: 4 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 3. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'data' "
        "  top: 'conv1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pool1ave' "
        "    type: 'pool' "
        "    pool: AVE "
        "    kernelsize: 3 "
        "    stride: 2 "
        "  } "
        "  bottom: 'conv1' "
        "  top: 'pool1ave' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pool1stoch' "
        "    type: 'pool' "
        "    pool: STOCHASTIC "
        "    kernelsize: 4 "
        "    stride: 5 "
        "  } "
        "  bottom: 'conv1' "
        "  top: 'pool1stoch' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'concat' "
        "    type: 'concat' "
        "    concat_dim: 2 "
        "  } "
        "  bottom: 'pool1ave' "
        "  bottom: 'pool1stoch' "
        "  top: 'pool1concat' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'norm1' "
        "    type: 'lrn' "
        "    local_size: 5 "
        "    alpha: 0.0001 "
        "    beta: 0.75 "
        "  } "
        "  bottom: 'pool1concat' "
        "  top: 'norm1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'fc6' "
        "    type: 'innerproduct' "
        "    num_output: 4096 "
        "    biasterm: false "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.005 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'norm1' "
        "  top: 'fc6' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu6' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'fc6' "
        "  top: 'fc6' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'drop6' "
        "    type: 'dropout' "
        "    dropout_ratio: 0.2 "
        "  } "
        "  bottom: 'fc6' "
        "  top: 'fc6' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'loss' "
        "    type: 'infogain_loss' "
        "    source: '/my/infogain/matrix' "
        "  } "
        "  bottom: 'fc6' "
        "  bottom: 'label' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'accuracy' "
        "    type: 'accuracy' "
        "  } "
        "} "
        "layers { "
        "  layer { "
        "    name: 'bnll' "
        "    type: 'bnll' "
        "  } "
        "} "
        "layers { "
        "  layer { "
        "    name: 'euclidean_loss' "
        "    type: 'euclidean_loss' "
        "  } "
        "} "
        "layers { "
        "  layer { "
        "    name: 'flatten' "
        "    type: 'flatten' "
        "  } "
        "} "
        "layers { "
        "  layer { "
        "    name: 'hdf5_output' "
        "    type: 'hdf5_output' "
        "    hdf5_output_param { "
        "      file_name: '/my/hdf5/output/file' "
        "    } "
        "  } "
        "} "
        "layers { "
        "  layer { "
        "    name: 'im2col' "
        "    type: 'im2col' "
        "  } "
        "} "
        "layers { "
        "  layer { "
        "    name: 'images' "
        "    type: 'images' "
        "  } "
        "} "
        "layers { "
        "  layer { "
        "    name: 'multinomial_logistic_loss' "
        "    type: 'multinomial_logistic_loss' "
        "  } "
        "} "
        "layers { "
        "  layer { "
        "    name: 'sigmoid' "
        "    type: 'sigmoid' "
        "  } "
        "} "
        "layers { "
        "  layer { "
        "    name: 'softmax' "
        "    type: 'softmax' "
        "  } "
        "} "
        "layers { "
        "  layer { "
        "    name: 'split' "
        "    type: 'split' "
        "  } "
        "} "
        "layers { "
        "  layer { "
        "    name: 'tanh' "
        "    type: 'tanh' "
        "  } "
        "} ";
    const string& expected_output_proto =
        "name: 'CaffeNet' "
        "input: 'input_data' "
        "input_dim: 64 "
        "input_dim: 3 "
        "input_dim: 32 "
        "input_dim: 32 "
        "layers { "
        "  name: 'data' "
        "  type: DATA "
        "  data_param { "
        "    source: '/home/jiayq/Data/ILSVRC12/train-leveldb' "
        "    batch_size: 256 "
        "    rand_skip: 73 "
        "  } "
        "  transform_param { "
        "    crop_size: 227 "
        "    mirror: true "
        "    scale: 0.25 "
        "    mean_file: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' "
        "  } "
        "  top: 'data' "
        "  top: 'label' "
        "} "
        "layers { "
        "  name: 'images' "
        "  type: IMAGE_DATA "
        "  image_data_param { "
        "    source: '/home/jiayq/Data/ILSVRC12/train-images' "
        "    batch_size: 256 "
        "    rand_skip: 73 "
        "    shuffle: true "
        "    new_height: 40 "
        "    new_width: 30 "
        "  } "
        "  transform_param {"
        "    mean_file: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' "
        "    crop_size: 227 "
        "    mirror: true "
        "    scale: 0.25 "
        "  } "
        "  top: 'images_data' "
        "  top: 'images_label' "
        "} "
        "layers { "
        "  name: 'window_data' "
        "  type: WINDOW_DATA "
        "  window_data_param { "
        "    source: '/home/jiayq/Data/ILSVRC12/train-leveldb' "
        "    batch_size: 256 "
        "    fg_threshold: 0.25 "
        "    bg_threshold: 0.75 "
        "    fg_fraction: 0.5 "
        "    context_pad: 16 "
        "    crop_mode: 'square' "
        "  } "
        "  transform_param { "
        "    mirror: true "
        "    crop_size: 227 "
        "    mean_file: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' "
        "  }"
        "  top: 'window_data' "
        "  top: 'window_label' "
        "} "
        "layers { "
        "  name: 'hdf5data' "
        "  type: HDF5_DATA "
        "  hdf5_data_param { "
        "    source: '/my/hdf5/data' "
        "    batch_size: 256 "
        "  } "
        "  top: 'hdf5data' "
        "} "
        "layers { "
        "  name: 'conv1' "
        "  type: CONVOLUTION "
        "  convolution_param { "
        "    num_output: 96 "
        "    bias_term: false "
        "    pad: 4 "
        "    kernel_size: 11 "
        "    stride: 4 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 3. "
        "    } "
        "  } "
        "  blobs_lr: 1. "
        "  blobs_lr: 2. "
        "  weight_decay: 1. "
        "  weight_decay: 0. "
        "  bottom: 'data' "
        "  top: 'conv1' "
        "} "
        "layers { "
        "  name: 'pool1ave' "
        "  type: POOLING "
        "  pooling_param { "
        "    pool: AVE "
        "    kernel_size: 3 "
        "    stride: 2 "
        "  } "
        "  bottom: 'conv1' "
        "  top: 'pool1ave' "
        "} "
        "layers { "
        "  name: 'pool1stoch' "
        "  type: POOLING "
        "  pooling_param { "
        "    pool: STOCHASTIC "
        "    kernel_size: 4 "
        "    stride: 5 "
        "  } "
        "  bottom: 'conv1' "
        "  top: 'pool1stoch' "
        "} "
        "layers { "
        "  name: 'concat' "
        "  type: CONCAT "
        "  concat_param { "
        "    concat_dim: 2 "
        "  } "
        "  bottom: 'pool1ave' "
        "  bottom: 'pool1stoch' "
        "  top: 'pool1concat' "
        "} "
        "layers { "
        "  name: 'norm1' "
        "  type: LRN "
        "  lrn_param { "
        "    local_size: 5 "
        "    alpha: 0.0001 "
        "    beta: 0.75 "
        "  } "
        "  bottom: 'pool1concat' "
        "  top: 'norm1' "
        "} "
        "layers { "
        "  name: 'fc6' "
        "  type: INNER_PRODUCT "
        "  inner_product_param { "
        "    num_output: 4096 "
        "    bias_term: false "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.005 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "  } "
        "  blobs_lr: 1. "
        "  blobs_lr: 2. "
        "  weight_decay: 1. "
        "  weight_decay: 0. "
        "  bottom: 'norm1' "
        "  top: 'fc6' "
        "} "
        "layers { "
        "  name: 'relu6' "
        "  type: RELU "
        "  bottom: 'fc6' "
        "  top: 'fc6' "
        "} "
        "layers { "
        "  name: 'drop6' "
        "  type: DROPOUT "
        "  dropout_param { "
        "    dropout_ratio: 0.2 "
        "  } "
        "  bottom: 'fc6' "
        "  top: 'fc6' "
        "} "
        "layers { "
        "  name: 'loss' "
        "  type: INFOGAIN_LOSS "
        "  infogain_loss_param { "
        "    source: '/my/infogain/matrix' "
        "  } "
        "  bottom: 'fc6' "
        "  bottom: 'label' "
        "} "
        "layers { "
        "  name: 'accuracy' "
        "  type: ACCURACY "
        "} "
        "layers { "
        "  name: 'bnll' "
        "  type: BNLL "
        "} "
        "layers { "
        "  name: 'euclidean_loss' "
        "  type: EUCLIDEAN_LOSS "
        "} "
        "layers { "
        "  name: 'flatten' "
        "  type: FLATTEN "
        "} "
        "layers { "
        "  name: 'hdf5_output' "
        "  type: HDF5_OUTPUT "
        "  hdf5_output_param { "
        "    file_name: '/my/hdf5/output/file' "
        "  } "
        "} "
        "layers { "
        "  name: 'im2col' "
        "  type: IM2COL "
        "} "
        "layers { "
        "  name: 'images' "
        "  type: IMAGE_DATA "
        "} "
        "layers { "
        "  name: 'multinomial_logistic_loss' "
        "  type: MULTINOMIAL_LOGISTIC_LOSS "
        "} "
        "layers { "
        "  name: 'sigmoid' "
        "  type: SIGMOID "
        "} "
        "layers { "
        "  name: 'softmax' "
        "  type: SOFTMAX "
        "} "
        "layers { "
        "  name: 'split' "
        "  type: SPLIT "
        "} "
        "layers { "
        "  name: 'tanh' "
        "  type: TANH "
        "} ";
    this->RunV0UpgradeTest(input_proto, expected_output_proto);
  }
  
  TEST_F(NetUpgradeTest, TestImageNet) {
    const string& v0_proto =
        "name: 'CaffeNet' "
        "layers { "
        "  layer { "
        "    name: 'data' "
        "    type: 'data' "
        "    source: '/home/jiayq/Data/ILSVRC12/train-leveldb' "
        "    meanfile: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' "
        "    batchsize: 256 "
        "    cropsize: 227 "
        "    mirror: true "
        "  } "
        "  top: 'data' "
        "  top: 'label' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv1' "
        "    type: 'conv' "
        "    num_output: 96 "
        "    kernelsize: 11 "
        "    stride: 4 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'data' "
        "  top: 'conv1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu1' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'conv1' "
        "  top: 'conv1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pool1' "
        "    type: 'pool' "
        "    pool: MAX "
        "    kernelsize: 3 "
        "    stride: 2 "
        "  } "
        "  bottom: 'conv1' "
        "  top: 'pool1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'norm1' "
        "    type: 'lrn' "
        "    local_size: 5 "
        "    alpha: 0.0001 "
        "    beta: 0.75 "
        "  } "
        "  bottom: 'pool1' "
        "  top: 'norm1' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pad2' "
        "    type: 'padding' "
        "    pad: 2 "
        "  } "
        "  bottom: 'norm1' "
        "  top: 'pad2' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv2' "
        "    type: 'conv' "
        "    num_output: 256 "
        "    group: 2 "
        "    kernelsize: 5 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'pad2' "
        "  top: 'conv2' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu2' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'conv2' "
        "  top: 'conv2' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pool2' "
        "    type: 'pool' "
        "    pool: MAX "
        "    kernelsize: 3 "
        "    stride: 2 "
        "  } "
        "  bottom: 'conv2' "
        "  top: 'pool2' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'norm2' "
        "    type: 'lrn' "
        "    local_size: 5 "
        "    alpha: 0.0001 "
        "    beta: 0.75 "
        "  } "
        "  bottom: 'pool2' "
        "  top: 'norm2' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pad3' "
        "    type: 'padding' "
        "    pad: 1 "
        "  } "
        "  bottom: 'norm2' "
        "  top: 'pad3' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv3' "
        "    type: 'conv' "
        "    num_output: 384 "
        "    kernelsize: 3 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'pad3' "
        "  top: 'conv3' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu3' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'conv3' "
        "  top: 'conv3' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pad4' "
        "    type: 'padding' "
        "    pad: 1 "
        "  } "
        "  bottom: 'conv3' "
        "  top: 'pad4' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv4' "
        "    type: 'conv' "
        "    num_output: 384 "
        "    group: 2 "
        "    kernelsize: 3 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'pad4' "
        "  top: 'conv4' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu4' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'conv4' "
        "  top: 'conv4' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pad5' "
        "    type: 'padding' "
        "    pad: 1 "
        "  } "
        "  bottom: 'conv4' "
        "  top: 'pad5' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'conv5' "
        "    type: 'conv' "
        "    num_output: 256 "
        "    group: 2 "
        "    kernelsize: 3 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'pad5' "
        "  top: 'conv5' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu5' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'conv5' "
        "  top: 'conv5' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'pool5' "
        "    type: 'pool' "
        "    kernelsize: 3 "
        "    pool: MAX "
        "    stride: 2 "
        "  } "
        "  bottom: 'conv5' "
        "  top: 'pool5' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'fc6' "
        "    type: 'innerproduct' "
        "    num_output: 4096 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.005 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'pool5' "
        "  top: 'fc6' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu6' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'fc6' "
        "  top: 'fc6' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'drop6' "
        "    type: 'dropout' "
        "    dropout_ratio: 0.5 "
        "  } "
        "  bottom: 'fc6' "
        "  top: 'fc6' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'fc7' "
        "    type: 'innerproduct' "
        "    num_output: 4096 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.005 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'fc6' "
        "  top: 'fc7' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'relu7' "
        "    type: 'relu' "
        "  } "
        "  bottom: 'fc7' "
        "  top: 'fc7' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'drop7' "
        "    type: 'dropout' "
        "    dropout_ratio: 0.5 "
        "  } "
        "  bottom: 'fc7' "
        "  top: 'fc7' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'fc8' "
        "    type: 'innerproduct' "
        "    num_output: 1000 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0 "
        "    } "
        "    blobs_lr: 1. "
        "    blobs_lr: 2. "
        "    weight_decay: 1. "
        "    weight_decay: 0. "
        "  } "
        "  bottom: 'fc7' "
        "  top: 'fc8' "
        "} "
        "layers { "
        "  layer { "
        "    name: 'loss' "
        "    type: 'softmax_loss' "
        "  } "
        "  bottom: 'fc8' "
        "  bottom: 'label' "
        "} ";
    const string& expected_v1_proto =
        "name: 'CaffeNet' "
        "layers { "
        "  name: 'data' "
        "  type: DATA "
        "  data_param { "
        "    source: '/home/jiayq/Data/ILSVRC12/train-leveldb' "
        "    batch_size: 256 "
        "  } "
        "  transform_param { "
        "    crop_size: 227 "
        "    mirror: true "
        "    mean_file: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' "
        "  } "
        "  top: 'data' "
        "  top: 'label' "
        "} "
        "layers { "
        "  name: 'conv1' "
        "  type: CONVOLUTION "
        "  convolution_param { "
        "    num_output: 96 "
        "    kernel_size: 11 "
        "    stride: 4 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "  } "
        "  blobs_lr: 1. "
        "  blobs_lr: 2. "
        "  weight_decay: 1. "
        "  weight_decay: 0. "
        "  bottom: 'data' "
        "  top: 'conv1' "
        "} "
        "layers { "
        "  name: 'relu1' "
        "  type: RELU "
        "  bottom: 'conv1' "
        "  top: 'conv1' "
        "} "
        "layers { "
        "  name: 'pool1' "
        "  type: POOLING "
        "  pooling_param { "
        "    pool: MAX "
        "    kernel_size: 3 "
        "    stride: 2 "
        "  } "
        "  bottom: 'conv1' "
        "  top: 'pool1' "
        "} "
        "layers { "
        "  name: 'norm1' "
        "  type: LRN "
        "  lrn_param { "
        "    local_size: 5 "
        "    alpha: 0.0001 "
        "    beta: 0.75 "
        "  } "
        "  bottom: 'pool1' "
        "  top: 'norm1' "
        "} "
        "layers { "
        "  name: 'conv2' "
        "  type: CONVOLUTION "
        "  convolution_param { "
        "    num_output: 256 "
        "    group: 2 "
        "    kernel_size: 5 "
        "    pad: 2 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "  } "
        "  blobs_lr: 1. "
        "  blobs_lr: 2. "
        "  weight_decay: 1. "
        "  weight_decay: 0. "
        "  bottom: 'norm1' "
        "  top: 'conv2' "
        "} "
        "layers { "
        "  name: 'relu2' "
        "  type: RELU "
        "  bottom: 'conv2' "
        "  top: 'conv2' "
        "} "
        "layers { "
        "  name: 'pool2' "
        "  type: POOLING "
        "  pooling_param { "
        "    pool: MAX "
        "    kernel_size: 3 "
        "    stride: 2 "
        "  } "
        "  bottom: 'conv2' "
        "  top: 'pool2' "
        "} "
        "layers { "
        "  name: 'norm2' "
        "  type: LRN "
        "  lrn_param { "
        "    local_size: 5 "
        "    alpha: 0.0001 "
        "    beta: 0.75 "
        "  } "
        "  bottom: 'pool2' "
        "  top: 'norm2' "
        "} "
        "layers { "
        "  name: 'conv3' "
        "  type: CONVOLUTION "
        "  convolution_param { "
        "    num_output: 384 "
        "    kernel_size: 3 "
        "    pad: 1 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "  } "
        "  blobs_lr: 1. "
        "  blobs_lr: 2. "
        "  weight_decay: 1. "
        "  weight_decay: 0. "
        "  bottom: 'norm2' "
        "  top: 'conv3' "
        "} "
        "layers { "
        "  name: 'relu3' "
        "  type: RELU "
        "  bottom: 'conv3' "
        "  top: 'conv3' "
        "} "
        "layers { "
        "  name: 'conv4' "
        "  type: CONVOLUTION "
        "  convolution_param { "
        "    num_output: 384 "
        "    group: 2 "
        "    kernel_size: 3 "
        "    pad: 1 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "  } "
        "  blobs_lr: 1. "
        "  blobs_lr: 2. "
        "  weight_decay: 1. "
        "  weight_decay: 0. "
        "  bottom: 'conv3' "
        "  top: 'conv4' "
        "} "
        "layers { "
        "  name: 'relu4' "
        "  type: RELU "
        "  bottom: 'conv4' "
        "  top: 'conv4' "
        "} "
        "layers { "
        "  name: 'conv5' "
        "  type: CONVOLUTION "
        "  convolution_param { "
        "    num_output: 256 "
        "    group: 2 "
        "    kernel_size: 3 "
        "    pad: 1 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "  } "
        "  blobs_lr: 1. "
        "  blobs_lr: 2. "
        "  weight_decay: 1. "
        "  weight_decay: 0. "
        "  bottom: 'conv4' "
        "  top: 'conv5' "
        "} "
        "layers { "
        "  name: 'relu5' "
        "  type: RELU "
        "  bottom: 'conv5' "
        "  top: 'conv5' "
        "} "
        "layers { "
        "  name: 'pool5' "
        "  type: POOLING "
        "  pooling_param { "
        "    kernel_size: 3 "
        "    pool: MAX "
        "    stride: 2 "
        "  } "
        "  bottom: 'conv5' "
        "  top: 'pool5' "
        "} "
        "layers { "
        "  name: 'fc6' "
        "  type: INNER_PRODUCT "
        "  inner_product_param { "
        "    num_output: 4096 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.005 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "  } "
        "  blobs_lr: 1. "
        "  blobs_lr: 2. "
        "  weight_decay: 1. "
        "  weight_decay: 0. "
        "  bottom: 'pool5' "
        "  top: 'fc6' "
        "} "
        "layers { "
        "  name: 'relu6' "
        "  type: RELU "
        "  bottom: 'fc6' "
        "  top: 'fc6' "
        "} "
        "layers { "
        "  name: 'drop6' "
        "  type: DROPOUT "
        "  dropout_param { "
        "    dropout_ratio: 0.5 "
        "  } "
        "  bottom: 'fc6' "
        "  top: 'fc6' "
        "} "
        "layers { "
        "  name: 'fc7' "
        "  type: INNER_PRODUCT "
        "  inner_product_param { "
        "    num_output: 4096 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.005 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "  } "
        "  blobs_lr: 1. "
        "  blobs_lr: 2. "
        "  weight_decay: 1. "
        "  weight_decay: 0. "
        "  bottom: 'fc6' "
        "  top: 'fc7' "
        "} "
        "layers { "
        "  name: 'relu7' "
        "  type: RELU "
        "  bottom: 'fc7' "
        "  top: 'fc7' "
        "} "
        "layers { "
        "  name: 'drop7' "
        "  type: DROPOUT "
        "  dropout_param { "
        "    dropout_ratio: 0.5 "
        "  } "
        "  bottom: 'fc7' "
        "  top: 'fc7' "
        "} "
        "layers { "
        "  name: 'fc8' "
        "  type: INNER_PRODUCT "
        "  inner_product_param { "
        "    num_output: 1000 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0 "
        "    } "
        "  } "
        "  blobs_lr: 1. "
        "  blobs_lr: 2. "
        "  weight_decay: 1. "
        "  weight_decay: 0. "
        "  bottom: 'fc7' "
        "  top: 'fc8' "
        "} "
        "layers { "
        "  name: 'loss' "
        "  type: SOFTMAX_LOSS "
        "  bottom: 'fc8' "
        "  bottom: 'label' "
        "} ";
    this->RunV0UpgradeTest(v0_proto, expected_v1_proto);
  
    const string& expected_v2_proto =
        "name: 'CaffeNet' "
        "layer { "
        "  name: 'data' "
        "  type: 'Data' "
        "  data_param { "
        "    source: '/home/jiayq/Data/ILSVRC12/train-leveldb' "
        "    batch_size: 256 "
        "  } "
        "  transform_param { "
        "    crop_size: 227 "
        "    mirror: true "
        "    mean_file: '/home/jiayq/Data/ILSVRC12/image_mean.binaryproto' "
        "  } "
        "  top: 'data' "
        "  top: 'label' "
        "} "
        "layer { "
        "  name: 'conv1' "
        "  type: 'Convolution' "
        "  convolution_param { "
        "    num_output: 96 "
        "    kernel_size: 11 "
        "    stride: 4 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "  } "
        "  param { "
        "    lr_mult: 1 "
        "    decay_mult: 1 "
        "  } "
        "  param { "
        "    lr_mult: 2 "
        "    decay_mult: 0 "
        "  } "
        "  bottom: 'data' "
        "  top: 'conv1' "
        "} "
        "layer { "
        "  name: 'relu1' "
        "  type: 'ReLU' "
        "  bottom: 'conv1' "
        "  top: 'conv1' "
        "} "
        "layer { "
        "  name: 'pool1' "
        "  type: 'Pooling' "
        "  pooling_param { "
        "    pool: MAX "
        "    kernel_size: 3 "
        "    stride: 2 "
        "  } "
        "  bottom: 'conv1' "
        "  top: 'pool1' "
        "} "
        "layer { "
        "  name: 'norm1' "
        "  type: 'LRN' "
        "  lrn_param { "
        "    local_size: 5 "
        "    alpha: 0.0001 "
        "    beta: 0.75 "
        "  } "
        "  bottom: 'pool1' "
        "  top: 'norm1' "
        "} "
        "layer { "
        "  name: 'conv2' "
        "  type: 'Convolution' "
        "  convolution_param { "
        "    num_output: 256 "
        "    group: 2 "
        "    kernel_size: 5 "
        "    pad: 2 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "  } "
        "  param { "
        "    lr_mult: 1 "
        "    decay_mult: 1 "
        "  } "
        "  param { "
        "    lr_mult: 2 "
        "    decay_mult: 0 "
        "  } "
        "  bottom: 'norm1' "
        "  top: 'conv2' "
        "} "
        "layer { "
        "  name: 'relu2' "
        "  type: 'ReLU' "
        "  bottom: 'conv2' "
        "  top: 'conv2' "
        "} "
        "layer { "
        "  name: 'pool2' "
        "  type: 'Pooling' "
        "  pooling_param { "
        "    pool: MAX "
        "    kernel_size: 3 "
        "    stride: 2 "
        "  } "
        "  bottom: 'conv2' "
        "  top: 'pool2' "
        "} "
        "layer { "
        "  name: 'norm2' "
        "  type: 'LRN' "
        "  lrn_param { "
        "    local_size: 5 "
        "    alpha: 0.0001 "
        "    beta: 0.75 "
        "  } "
        "  bottom: 'pool2' "
        "  top: 'norm2' "
        "} "
        "layer { "
        "  name: 'conv3' "
        "  type: 'Convolution' "
        "  convolution_param { "
        "    num_output: 384 "
        "    kernel_size: 3 "
        "    pad: 1 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0. "
        "    } "
        "  } "
        "  param { "
        "    lr_mult: 1 "
        "    decay_mult: 1 "
        "  } "
        "  param { "
        "    lr_mult: 2 "
        "    decay_mult: 0 "
        "  } "
        "  bottom: 'norm2' "
        "  top: 'conv3' "
        "} "
        "layer { "
        "  name: 'relu3' "
        "  type: 'ReLU' "
        "  bottom: 'conv3' "
        "  top: 'conv3' "
        "} "
        "layer { "
        "  name: 'conv4' "
        "  type: 'Convolution' "
        "  convolution_param { "
        "    num_output: 384 "
        "    group: 2 "
        "    kernel_size: 3 "
        "    pad: 1 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "  } "
        "  param { "
        "    lr_mult: 1 "
        "    decay_mult: 1 "
        "  } "
        "  param { "
        "    lr_mult: 2 "
        "    decay_mult: 0 "
        "  } "
        "  bottom: 'conv3' "
        "  top: 'conv4' "
        "} "
        "layer { "
        "  name: 'relu4' "
        "  type: 'ReLU' "
        "  bottom: 'conv4' "
        "  top: 'conv4' "
        "} "
        "layer { "
        "  name: 'conv5' "
        "  type: 'Convolution' "
        "  convolution_param { "
        "    num_output: 256 "
        "    group: 2 "
        "    kernel_size: 3 "
        "    pad: 1 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "  } "
        "  param { "
        "    lr_mult: 1 "
        "    decay_mult: 1 "
        "  } "
        "  param { "
        "    lr_mult: 2 "
        "    decay_mult: 0 "
        "  } "
        "  bottom: 'conv4' "
        "  top: 'conv5' "
        "} "
        "layer { "
        "  name: 'relu5' "
        "  type: 'ReLU' "
        "  bottom: 'conv5' "
        "  top: 'conv5' "
        "} "
        "layer { "
        "  name: 'pool5' "
        "  type: 'Pooling' "
        "  pooling_param { "
        "    kernel_size: 3 "
        "    pool: MAX "
        "    stride: 2 "
        "  } "
        "  bottom: 'conv5' "
        "  top: 'pool5' "
        "} "
        "layer { "
        "  name: 'fc6' "
        "  type: 'InnerProduct' "
        "  inner_product_param { "
        "    num_output: 4096 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.005 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "  } "
        "  param { "
        "    lr_mult: 1 "
        "    decay_mult: 1 "
        "  } "
        "  param { "
        "    lr_mult: 2 "
        "    decay_mult: 0 "
        "  } "
        "  bottom: 'pool5' "
        "  top: 'fc6' "
        "} "
        "layer { "
        "  name: 'relu6' "
        "  type: 'ReLU' "
        "  bottom: 'fc6' "
        "  top: 'fc6' "
        "} "
        "layer { "
        "  name: 'drop6' "
        "  type: 'Dropout' "
        "  dropout_param { "
        "    dropout_ratio: 0.5 "
        "  } "
        "  bottom: 'fc6' "
        "  top: 'fc6' "
        "} "
        "layer { "
        "  name: 'fc7' "
        "  type: 'InnerProduct' "
        "  inner_product_param { "
        "    num_output: 4096 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.005 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 1. "
        "    } "
        "  } "
        "  param { "
        "    lr_mult: 1 "
        "    decay_mult: 1 "
        "  } "
        "  param { "
        "    lr_mult: 2 "
        "    decay_mult: 0 "
        "  } "
        "  bottom: 'fc6' "
        "  top: 'fc7' "
        "} "
        "layer { "
        "  name: 'relu7' "
        "  type: 'ReLU' "
        "  bottom: 'fc7' "
        "  top: 'fc7' "
        "} "
        "layer { "
        "  name: 'drop7' "
        "  type: 'Dropout' "
        "  dropout_param { "
        "    dropout_ratio: 0.5 "
        "  } "
        "  bottom: 'fc7' "
        "  top: 'fc7' "
        "} "
        "layer { "
        "  name: 'fc8' "
        "  type: 'InnerProduct' "
        "  inner_product_param { "
        "    num_output: 1000 "
        "    weight_filler { "
        "      type: 'gaussian' "
        "      std: 0.01 "
        "    } "
        "    bias_filler { "
        "      type: 'constant' "
        "      value: 0 "
        "    } "
        "  } "
        "  param { "
        "    lr_mult: 1 "
        "    decay_mult: 1 "
        "  } "
        "  param { "
        "    lr_mult: 2 "
        "    decay_mult: 0 "
        "  } "
        "  bottom: 'fc7' "
        "  top: 'fc8' "
        "} "
        "layer { "
        "  name: 'loss' "
        "  type: 'SoftmaxWithLoss' "
        "  bottom: 'fc8' "
        "  bottom: 'label' "
        "} ";
    this->RunV1UpgradeTest(expected_v1_proto, expected_v2_proto);
  }  // NOLINT(readability/fn_size)
  
  TEST_F(NetUpgradeTest, TestUpgradeV1LayerType) {
    LayerParameter layer_param;
    shared_ptr<Layer<float> > layer;
    for (int i = 0; i < V1LayerParameter_LayerType_LayerType_ARRAYSIZE; ++i) {
      ASSERT_TRUE(V1LayerParameter_LayerType_IsValid(i));
      V1LayerParameter_LayerType v1_type = V1LayerParameter_LayerType(i);
      string v2_layer_type(UpgradeV1LayerType(v1_type));
      if (v2_layer_type == "") {
        EXPECT_EQ(V1LayerParameter_LayerType_NONE, v1_type);
        continue;  // Empty string isn't actually a valid layer type.
      }
      layer_param.set_type(v2_layer_type);
      layer = LayerRegistry<float>::CreateLayer(layer_param);
      EXPECT_EQ(v2_layer_type, layer->type());
    }
  }
  
  }  // NOLINT(readability/fn_size)  // namespace caffe
  